From ee2d5ddeb1aa14fa2351ebad880439816c2584ef Mon Sep 17 00:00:00 2001 From: Martin Vladic Date: Sun, 6 Oct 2024 17:05:41 +0200 Subject: [PATCH] #580 --- docs/components/html/en-US/LVGL.html | 16 +- .../en-US/actions/AddToInstrumentHistory.odt | Bin 339907 -> 339907 bytes docs/components/odt/en-US/actions/Animate.odt | Bin 78142 -> 78142 bytes .../components/odt/en-US/actions/CSVParse.odt | Bin 115464 -> 115464 bytes .../odt/en-US/actions/CSVStringify.odt | Bin 77975 -> 77975 bytes .../odt/en-US/actions/CatchError.odt | Bin 77489 -> 77489 bytes .../odt/en-US/actions/ClipboardWrite.odt | Bin 77467 -> 77467 bytes .../odt/en-US/actions/CloseStream.odt | Bin 77382 -> 77382 bytes .../odt/en-US/actions/CollectStream.odt | Bin 77766 -> 77766 bytes docs/components/odt/en-US/actions/Comment.odt | Bin 72818 -> 72818 bytes docs/components/odt/en-US/actions/Compare.odt | Bin 78141 -> 78141 bytes .../odt/en-US/actions/ConnectInstrument.odt | Bin 77572 -> 77572 bytes .../components/odt/en-US/actions/Constant.odt | Bin 77683 -> 77683 bytes docs/components/odt/en-US/actions/Counter.odt | Bin 90222 -> 90222 bytes docs/components/odt/en-US/actions/DateNow.odt | Bin 77389 -> 77389 bytes docs/components/odt/en-US/actions/Delay.odt | Bin 77511 -> 77511 bytes .../en-US/actions/DisconnectInstrument.odt | Bin 77550 -> 77550 bytes .../odt/en-US/actions/DynamicCallAction.odt | Bin 77511 -> 77511 bytes docs/components/odt/en-US/actions/End.odt | Bin 77628 -> 77628 bytes docs/components/odt/en-US/actions/Error.odt | Bin 77515 -> 77515 bytes docs/components/odt/en-US/actions/Eval JS.odt | Bin 77705 -> 77705 bytes .../components/odt/en-US/actions/Evaluate.odt | Bin 77530 -> 77530 bytes .../odt/en-US/actions/ExecuteCommand.odt | Bin 77863 -> 77863 bytes .../odt/en-US/actions/FileAppend.odt | Bin 77640 -> 77640 bytes .../odt/en-US/actions/FileOpenDialog.odt | Bin 77624 -> 77624 bytes .../components/odt/en-US/actions/FileRead.odt | Bin 77780 -> 77780 bytes .../odt/en-US/actions/FileSaveDialog.odt | Bin 77780 -> 77780 bytes .../odt/en-US/actions/FileWrite.odt | Bin 77714 -> 77714 bytes .../odt/en-US/actions/GetInstrument.odt | Bin 234232 -> 234232 bytes .../en-US/actions/GetInstrumentProperties.odt | Bin 387246 -> 387246 bytes docs/components/odt/en-US/actions/HTTP.odt | Bin 77892 -> 77892 bytes docs/components/odt/en-US/actions/Input.odt | Bin 77462 -> 77462 bytes .../odt/en-US/actions/InstrumentRead.odt | Bin 77543 -> 77543 bytes .../odt/en-US/actions/InstrumentWrite.odt | Bin 77510 -> 77510 bytes docs/components/odt/en-US/actions/IsTrue.odt | Bin 77877 -> 77877 bytes .../odt/en-US/actions/JSONParse.odt | Bin 114418 -> 114418 bytes .../odt/en-US/actions/JSONStringify.odt | Bin 77644 -> 77644 bytes docs/components/odt/en-US/actions/LVGL.odt | Bin 80240 -> 80246 bytes .../components/odt/en-US/actions/Label IN.odt | Bin 77566 -> 77566 bytes .../odt/en-US/actions/Label OUT.odt | Bin 77566 -> 77566 bytes docs/components/odt/en-US/actions/Log.odt | Bin 77606 -> 77606 bytes docs/components/odt/en-US/actions/Loop.odt | Bin 104239 -> 104239 bytes .../odt/en-US/actions/MQTTConnect.odt | Bin 77841 -> 77841 bytes .../odt/en-US/actions/MQTTDisconnect.odt | Bin 77679 -> 77679 bytes .../odt/en-US/actions/MQTTEvent.odt | Bin 78319 -> 78319 bytes .../components/odt/en-US/actions/MQTTInit.odt | Bin 77985 -> 77985 bytes .../odt/en-US/actions/MQTTPublish.odt | Bin 77661 -> 77661 bytes .../odt/en-US/actions/MQTTSubscribe.odt | Bin 78115 -> 78115 bytes .../odt/en-US/actions/MQTTUnsubscribe.odt | Bin 77599 -> 77599 bytes docs/components/odt/en-US/actions/Modbus.odt | Bin 78353 -> 78353 bytes docs/components/odt/en-US/actions/NoOp.odt | Bin 77456 -> 77456 bytes docs/components/odt/en-US/actions/OnEvent.odt | Bin 77940 -> 77940 bytes docs/components/odt/en-US/actions/Output.odt | Bin 77456 -> 77456 bytes .../odt/en-US/actions/OverrideStyle.odt | Bin 77495 -> 77495 bytes .../odt/en-US/actions/PrintToPDF.odt | Bin 78080 -> 78080 bytes .../odt/en-US/actions/PythonEnd.odt | Bin 77586 -> 77586 bytes .../odt/en-US/actions/PythonRun.odt | Bin 78232 -> 78232 bytes .../odt/en-US/actions/PythonSendMessage.odt | Bin 77755 -> 77755 bytes .../odt/en-US/actions/ReadSetting.odt | Bin 77732 -> 77732 bytes docs/components/odt/en-US/actions/Regexp.odt | Bin 78486 -> 78486 bytes docs/components/odt/en-US/actions/SCPI.odt | Bin 147291 -> 147291 bytes .../odt/en-US/actions/SelectInstrument.odt | Bin 125928 -> 125928 bytes .../odt/en-US/actions/SelectLanguage.odt | Bin 77618 -> 77618 bytes .../odt/en-US/actions/SerialConnect.odt | Bin 77571 -> 77571 bytes .../odt/en-US/actions/SerialDisconnect.odt | Bin 77524 -> 77524 bytes .../odt/en-US/actions/SerialInit.odt | Bin 77767 -> 77767 bytes .../odt/en-US/actions/SerialListPorts.odt | Bin 77611 -> 77611 bytes .../odt/en-US/actions/SerialRead.odt | Bin 77567 -> 77567 bytes .../odt/en-US/actions/SerialWrite.odt | Bin 77515 -> 77515 bytes .../odt/en-US/actions/SetPageDirection.odt | Bin 77459 -> 77459 bytes .../odt/en-US/actions/SetVariable.odt | Bin 77494 -> 77494 bytes .../odt/en-US/actions/ShowFileInFolder.odt | Bin 77507 -> 77507 bytes .../odt/en-US/actions/ShowKeyboard.odt | Bin 106975 -> 106975 bytes .../odt/en-US/actions/ShowKeypad.odt | Bin 90713 -> 90713 bytes .../odt/en-US/actions/ShowMessageBox.odt | Bin 99097 -> 99097 bytes .../components/odt/en-US/actions/ShowPage.odt | Bin 77438 -> 77438 bytes .../odt/en-US/actions/SortArray.odt | Bin 78023 -> 78023 bytes docs/components/odt/en-US/actions/Start.odt | Bin 77404 -> 77404 bytes .../odt/en-US/actions/SwitchCase.odt | Bin 77910 -> 77910 bytes .../odt/en-US/actions/TCPConnect.odt | Bin 77632 -> 77632 bytes .../odt/en-US/actions/TCPDisconnect.odt | Bin 77540 -> 77540 bytes .../components/odt/en-US/actions/TCPEvent.odt | Bin 78078 -> 78078 bytes .../odt/en-US/actions/TCPListen.odt | Bin 77775 -> 77775 bytes .../components/odt/en-US/actions/TCPWrite.odt | Bin 77529 -> 77529 bytes .../odt/en-US/actions/TabulatorAction.odt | Bin 77829 -> 77829 bytes .../odt/en-US/actions/TestAndSet.odt | Bin 99711 -> 99711 bytes docs/components/odt/en-US/actions/UDP In.odt | Bin 78018 -> 78018 bytes docs/components/odt/en-US/actions/UDP Out.odt | Bin 77982 -> 77982 bytes docs/components/odt/en-US/actions/Watch.odt | Bin 77663 -> 77663 bytes .../odt/en-US/actions/WriteSetting.odt | Bin 77710 -> 77710 bytes .../odt/en-US/widgets/AnimationImage.odt | Bin 84066 -> 84066 bytes docs/components/odt/en-US/widgets/Arc.odt | Bin 84558 -> 84558 bytes docs/components/odt/en-US/widgets/Bar.odt | Bin 84556 -> 84556 bytes .../components/odt/en-US/widgets/BarGraph.odt | Bin 126557 -> 126557 bytes .../odt/en-US/widgets/Bitmap (Dashboard).odt | Bin 126385 -> 126385 bytes .../odt/en-US/widgets/Bitmap (EEZ-GUI).odt | Bin 125915 -> 125915 bytes .../odt/en-US/widgets/Button (Dashboard).odt | Bin 126123 -> 126123 bytes .../odt/en-US/widgets/Button (EEZ-GUI).odt | Bin 125999 -> 125999 bytes .../odt/en-US/widgets/Button (LVGL).odt | Bin 83867 -> 83867 bytes .../odt/en-US/widgets/ButtonGroup.odt | Bin 126033 -> 126033 bytes .../odt/en-US/widgets/ButtonMatrix.odt | Bin 84511 -> 84511 bytes .../components/odt/en-US/widgets/Calendar.odt | Bin 83912 -> 83912 bytes docs/components/odt/en-US/widgets/Canvas.odt | Bin 83811 -> 83811 bytes docs/components/odt/en-US/widgets/Chart.odt | Bin 83810 -> 83810 bytes .../en-US/widgets/Checkbox (Dashboard).odt | Bin 125981 -> 125981 bytes .../odt/en-US/widgets/Checkbox (LVGL).odt | Bin 83894 -> 83894 bytes .../odt/en-US/widgets/Colorwheel.odt | Bin 84004 -> 84004 bytes .../en-US/widgets/Container (Dashboard).odt | Bin 126621 -> 126621 bytes .../odt/en-US/widgets/Container (LVGL).odt | Bin 83685 -> 83685 bytes .../odt/en-US/widgets/DisplayData.odt | Bin 126223 -> 126223 bytes .../en-US/widgets/Dropdown (Dashboard).odt | Bin 125966 -> 125966 bytes .../odt/en-US/widgets/Dropdown (EEZ-GUI).odt | Bin 125786 -> 125786 bytes .../odt/en-US/widgets/Dropdown (LVGL).odt | Bin 84232 -> 84232 bytes .../components/odt/en-US/widgets/EEZChart.odt | Bin 155700 -> 155700 bytes .../odt/en-US/widgets/Embedded Dashboard.odt | Bin 126048 -> 126048 bytes .../odt/en-US/widgets/Gauge (Dashboard).odt | Bin 139360 -> 139360 bytes .../odt/en-US/widgets/Gauge (EEZ-GUI).odt | Bin 126231 -> 126231 bytes docs/components/odt/en-US/widgets/Grid.odt | Bin 156174 -> 156174 bytes docs/components/odt/en-US/widgets/Image.odt | Bin 84443 -> 84443 bytes .../odt/en-US/widgets/Imgbutton.odt | Bin 84106 -> 84106 bytes .../odt/en-US/widgets/Input (EEZ-GUI).odt | Bin 126309 -> 126309 bytes .../odt/en-US/widgets/InstrumentTerminal.odt | Bin 332016 -> 332016 bytes .../components/odt/en-US/widgets/Keyboard.odt | Bin 84063 -> 84063 bytes docs/components/odt/en-US/widgets/Label.odt | Bin 84511 -> 84511 bytes docs/components/odt/en-US/widgets/Led.odt | Bin 84037 -> 84037 bytes docs/components/odt/en-US/widgets/Line.odt | Bin 83985 -> 83985 bytes .../en-US/widgets/LineChart (Dashboard).odt | Bin 143296 -> 143296 bytes .../odt/en-US/widgets/LineChart (EEZ-GUI).odt | Bin 155168 -> 155168 bytes .../odt/en-US/widgets/List (Dashboard).odt | Bin 126586 -> 126586 bytes .../odt/en-US/widgets/List (LVGL).odt | Bin 83832 -> 83832 bytes docs/components/odt/en-US/widgets/Lottie.odt | Bin 83833 -> 83833 bytes .../components/odt/en-US/widgets/Markdown.odt | Bin 125823 -> 125823 bytes docs/components/odt/en-US/widgets/Menu.odt | Bin 83832 -> 83832 bytes .../odt/en-US/widgets/MessageBox.odt | Bin 83839 -> 83839 bytes docs/components/odt/en-US/widgets/Meter.odt | Bin 84042 -> 84042 bytes .../odt/en-US/widgets/MultilineText.odt | Bin 126029 -> 126029 bytes .../odt/en-US/widgets/NumberInput.odt | Bin 125976 -> 125976 bytes docs/components/odt/en-US/widgets/Panel.odt | Bin 83899 -> 83899 bytes docs/components/odt/en-US/widgets/Plotly.odt | Bin 125994 -> 125994 bytes .../en-US/widgets/Progress (Dashboard).odt | Bin 126068 -> 126068 bytes .../odt/en-US/widgets/Progress (EEZ-GUI).odt | Bin 127283 -> 127283 bytes .../odt/en-US/widgets/QRCode (Dashboard).odt | Bin 126000 -> 126000 bytes .../odt/en-US/widgets/QRCode (EEZ-GUI).odt | Bin 125880 -> 125880 bytes docs/components/odt/en-US/widgets/Radio.odt | Bin 126157 -> 126157 bytes .../en-US/widgets/Rectangle (Dashboard).odt | Bin 125848 -> 125848 bytes .../odt/en-US/widgets/Rectangle (EEZ-GUI).odt | Bin 125640 -> 125640 bytes .../odt/en-US/widgets/Roller (EEZ-GUI).odt | Bin 126345 -> 126345 bytes .../odt/en-US/widgets/Roller (LVGL).odt | Bin 84245 -> 84245 bytes docs/components/odt/en-US/widgets/Scale.odt | Bin 84024 -> 84024 bytes .../odt/en-US/widgets/ScrollBar.odt | Bin 156501 -> 156501 bytes docs/components/odt/en-US/widgets/Select.odt | Bin 126021 -> 126021 bytes .../odt/en-US/widgets/Slider (Dashboard).odt | Bin 126150 -> 126150 bytes .../odt/en-US/widgets/Slider (EEZ-GUI).odt | Bin 125852 -> 125852 bytes .../odt/en-US/widgets/Slider (LVGL).odt | Bin 84516 -> 84516 bytes docs/components/odt/en-US/widgets/Span.odt | Bin 83830 -> 83830 bytes docs/components/odt/en-US/widgets/Spinbox.odt | Bin 84547 -> 84547 bytes .../odt/en-US/widgets/Spinner (Dashboard).odt | Bin 125810 -> 125810 bytes .../odt/en-US/widgets/Spinner (LVGL).odt | Bin 83804 -> 83804 bytes .../odt/en-US/widgets/Switch (Dashboard).odt | Bin 125923 -> 125923 bytes .../odt/en-US/widgets/Switch (EEZ-GUI).odt | Bin 125748 -> 125748 bytes .../odt/en-US/widgets/Switch (LVGL).odt | Bin 83834 -> 83834 bytes docs/components/odt/en-US/widgets/Tab.odt | Bin 83923 -> 83923 bytes docs/components/odt/en-US/widgets/Table.odt | Bin 83828 -> 83828 bytes .../odt/en-US/widgets/Tabulator.odt | Bin 126188 -> 126188 bytes docs/components/odt/en-US/widgets/Tabview.odt | Bin 89612 -> 89612 bytes .../components/odt/en-US/widgets/Terminal.odt | Bin 126181 -> 126181 bytes .../odt/en-US/widgets/Text (Dashboard).odt | Bin 126034 -> 126034 bytes .../odt/en-US/widgets/Text (EEZ-GUI).odt | Bin 125977 -> 125977 bytes .../odt/en-US/widgets/TextInput.odt | Bin 126072 -> 126072 bytes .../components/odt/en-US/widgets/Textarea.odt | Bin 84487 -> 84487 bytes .../components/odt/en-US/widgets/TileView.odt | Bin 83840 -> 83840 bytes .../odt/en-US/widgets/ToggleButton.odt | Bin 125876 -> 125876 bytes docs/components/odt/en-US/widgets/UpDown.odt | Bin 125984 -> 125984 bytes docs/components/odt/en-US/widgets/Window.odt | Bin 83832 -> 83832 bytes help/en-US/components/actions/LVGL.md | 94 +- .../_stylesheets/project-editor.less | 20 + packages/project-editor/lvgl/actions.tsx | 6034 +++++++++-------- 177 files changed, 3178 insertions(+), 2986 deletions(-) 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 7005cbd96a01165b277e4fd928c57ad88365f392..340e8ef1223e8816e57b84fa6cb2833e4f9ba977 100644 GIT binary patch delta 192 zcmX?nU*zz85uN~VW)=|!4j{}g*~lXy%9LNSSxwZQsd+-(_6c>2NjEm9ifgC0e+pyT z{wa+4j_`KNh0O70({)Xl1*iX2XXV*0oXxCe)?RR(d3(WimRY_){nL3=STayEIrW*#Y_qJ$e8D delta 202 zcmX?nU*zz85uN~VW)=|!4j^nP+{hy#%G6T0SxwZQY5Vc_jN0kb#W%6=PVYU!B-Pv_ zzP(4B(fUUFr!c1NpTd~$2v0A#&aAOrcOkR0+4gf;%<*Q^&uFm9wr{=8ynX9+mQY`y zQPX);S_@t E0GNCaVgLXD delta 52 zcmdn@h-Kd+7M=iaW)=|!4j^nU+{lwFz|>sWTrIG@T7c1763CvuLzB@QNN@kB$>_@t E0G>||rT_o{ diff --git a/docs/components/odt/en-US/actions/CSVParse.odt b/docs/components/odt/en-US/actions/CSVParse.odt index 0c5b619c2ccd757afcf50e36a2a238bd08855c86..83ffda15aba8d68a6fffccc6eebd13590c50a8bd 100644 GIT binary patch delta 52 zcmeBZWAA8V=Lzs;W)WfF0K$TjjXa5hOa&#)`GVW?1sStf0@>5=>|!(r(%VIMGk#_V E0CP_d_y7O^ delta 52 zcmeBZWAA8V=Lzs;W)WfF0K%5SjXa5hOf7}Y`GVW?1sStf0@>5=>|!(r(%VIMGk#_V E0C^%1JOBUy diff --git a/docs/components/odt/en-US/actions/CSVStringify.odt b/docs/components/odt/en-US/actions/CSVStringify.odt index 7986c6604e74aa99fe5998bcc0d7ef1d9c718c60..780be1be380ad0102e948145db86b7d2a3aff0b2 100644 GIT binary patch delta 52 zcmbRKkY)Nq7M=iaW)=|!4j?Qj*~oK@pQ)gv`3nE`EBuVsl0f!!K}|+;Aidp7lhKzQ E0GJ{U&;S4c delta 52 zcmbRKkY)Nq7M=iaW)=|!4j^nP+{kl`pQ)v=`3nE`EBuVsl0f!!K}|+;Aidp7lhKzQ E0G;&@6aWAK diff --git a/docs/components/odt/en-US/actions/CatchError.odt b/docs/components/odt/en-US/actions/CatchError.odt index b37c14b36ab369106f80befb4bb55b292a03f33b..2667e1b5aba4d37b0108bed362de63b1f4fe9f03 100644 GIT binary patch delta 52 zcmdmZmu2H!7M=iaW)=|!4j{}g*~s&Nmnpxb`5o`}cf5?&l0f!!ZFNR-AiX_Boza&a E0I7=)Z~y=R delta 52 zcmdmZmu2H!7M=iaW)=|!4j^nU+{p8Qm#Mk1`5o`}cf5?&l0f!!ZFNR-AiX_Boza&a E0IyyTv;Y7A diff --git a/docs/components/odt/en-US/actions/ClipboardWrite.odt b/docs/components/odt/en-US/actions/ClipboardWrite.odt index 728a62fff27b3fc7dfaac2ae52cb6c5888c45c46..eff7190c687778446504f6934daf92230e731b37 100644 GIT binary patch delta 52 zcmbPzmu2={7M=iaW)=|!4j{}g*~oK>mnpxb`3CRy8@!Cxl0f!!QFTUhAidpBoza&a E0GOQ))&Kwi delta 52 zcmbPzmu2={7M=iaW)=|!4j^nU+{kl^m#Mk1`3CRy8@!Cxl0f!!QFTUhAidpBoza&a E0G@CU8UO$Q diff --git a/docs/components/odt/en-US/actions/CloseStream.odt b/docs/components/odt/en-US/actions/CloseStream.odt index e2ffbc02588eaf3ebedbce7aa344a5b728512f7a..e5fa5097de3b3eba17c53f4700f3a2c798b6ed71 100644 GIT binary patch delta 52 zcmX?hhvnEE7M=iaW)=|!4j{}g*~nAM%amWz+|0YZnU~R863Cu@K#kEHNN@kC#^}oq E0GmM%e*gdg delta 52 zcmX?hhvnEE7M=iaW)=|!4j^nP+{jbP%hXcX+|0YZnU~R863Cu@K#kEHNN@kC#^}oq E0HJFS#{d8T diff --git a/docs/components/odt/en-US/actions/CollectStream.odt b/docs/components/odt/en-US/actions/CollectStream.odt index 38a6de6e28d3aec814d1c0e2b57e945f5a2ed13e..7a0f0d83165174f15d70cd46cb6a26df0e7a3a75 100644 GIT binary patch delta 52 zcmX?hpXJzn7M=iaW)=|!4j{}g*~s&ik14;TnVEk(Ge4uXB#=GbL4(m8NN=yyVDx1N E0E_|-4gdfE delta 52 zcmX?hpXJzn7M=iaW)=|!4j^nP+{p8lkEx}wnVEk(Ge4uXB#=GbL4(m8NN=yyVDx1N E0Fo>YRsaA1 diff --git a/docs/components/odt/en-US/actions/Comment.odt b/docs/components/odt/en-US/actions/Comment.odt index f64ed33a950ca2c514cb162ca2f7c0e7a5875865..74973db768b3061b7898bd5add33399defd6723a 100644 GIT binary patch delta 52 zcmeyggXPl>7M=iaW)=|!4j{}g*~nAP!IWRp+{v-MlY=pj2gsiOQ-skRNN+b1WprQ% E0H3)I`Tzg` delta 52 zcmeyggXPl>7M=iaW)=|!4j^nP+{jbS!PHXN+{v-MlY=pj2gsiOQ-skRNN+b1WprQ% E0Hxy(LI3~& diff --git a/docs/components/odt/en-US/actions/Compare.odt b/docs/components/odt/en-US/actions/Compare.odt index 212f5cbacac1dcf0c8a6e5fdf2bc4f0e8966d316..acdf1a9bfa092995fdfe84480911e9f07c45ee8e 100644 GIT binary patch delta 52 zcmdn{h-L317M=iaW)=|!4j{}g*~pV4z?5IoTqUr*N`TQ?63CvuU6auqNN@k3$>_@t E0GGE9TL1t6 delta 52 zcmdn{h-L317M=iaW)=|!4j^nU+{lw7z|>sWTqUr*N`TQ?63CvuU6auqNN@k3$>_@t E0G)~tp8x;= diff --git a/docs/components/odt/en-US/actions/ConnectInstrument.odt b/docs/components/odt/en-US/actions/ConnectInstrument.odt index c3490aa9f132daeaba7829d04b9098760d367835..848ddbb1022d2a8b046a89735cd15a5dc8d32158 100644 GIT binary patch delta 52 zcmZp<$I^0-g(tw9nMH(w0|@g=Hu4zrG3A#uJMwLJFwLq8GYFS DX_yVV delta 52 zcmZp<$I^0-g(tw9nMH(w0|;9RH}V+sF|`ynJMwLJFwLq8GYFS DZ^8}& diff --git a/docs/components/odt/en-US/actions/Constant.odt b/docs/components/odt/en-US/actions/Constant.odt index e4ae55c0dd3114b0520116a05fd282f16c00eda4..ed1a41792c4e138e90feea49c12003cb72b1f3bc 100644 GIT binary patch delta 52 zcmex-kLB|{7M=iaW)=|!4j{}g*~qhqk14;Tc>~|}4SbB&l0f$Kx9W`MKzh5H2BR-K E0J;Yc!~g&Q delta 52 zcmex-kLB|{7M=iaW)=|!4j^nU+{m+tkEyw^c>~|}4SbB&l0f$Kx9W`MKzh5H2BR-K E0KeK02mk;8 diff --git a/docs/components/odt/en-US/actions/Counter.odt b/docs/components/odt/en-US/actions/Counter.odt index 9de9acaada25c772ee657b9456943b598e780cb8..439a95f8bd65de334268cc761dbb65b639219536 100644 GIT binary patch delta 52 zcmaENfc4!0R-OQFW)=|!4j{}g*~nwd$CO{v?9I2`n~yQl3&@_nEP~M-NN>L%!Pw6Z E0GCYL%!Pw6Z E0G%KY`2YX_ diff --git a/docs/components/odt/en-US/actions/DateNow.odt b/docs/components/odt/en-US/actions/DateNow.odt index e43ea24ec66a897fff58702506b889a8fc638be2..aa2bd18e3a1e7a578b0456761b6273078f339bf4 100644 GIT binary patch delta 51 zcmX?mhvn=Y7M=iaW)=|!4j{}g*~nAF%amWz+{L@SiDkB#=GbQJv8oNN=xFXY^$U E0E?y$3;+NC delta 52 zcmX?pm*x0f7M=iaW)=|!4j^nU+{p8dm#Mk1nT2mV3m>DkB#=GbQJv8oNN=xFXY^$U E0FikPPyhe` diff --git a/docs/components/odt/en-US/actions/DisconnectInstrument.odt b/docs/components/odt/en-US/actions/DisconnectInstrument.odt index 402acec0408626b198b46df8f9b8370b0a053842..8ae8c6d85ba7f8a123550d5304f6b6871e6e6d2f 100644 GIT binary patch delta 52 zcmaENm*w4E7M=iaW)=|!4j{}g*~lZy$CO{vtj)Jwn~%|263CvOq0VRyq_;0rXY^$U E0E)*B9smFU delta 52 zcmaENm*w4E7M=iaW)=|!4j^nP+{h!#$JA2Ttj)Jwn~%|263CvOq0VRyq_;0rXY^$U E0FdzxW&i*H diff --git a/docs/components/odt/en-US/actions/DynamicCallAction.odt b/docs/components/odt/en-US/actions/DynamicCallAction.odt index 03b42157492e0058faf68031f82de7357dfef984..0198521b0290f85f51db930036e05c7980a040ef 100644 GIT binary patch delta 52 zcmX?pm*x0f7M=iaW)=|!4j{}g*~s&amnpxbnT2mV3m>DkB#=GbQJv8oNN=xFXY^$U E0E?y$3;+NC delta 52 zcmX?pm*x0f7M=iaW)=|!4j^nU+{p8dm#Mk1nT2mV3m>DkB#=GbQJv8oNN=xFXY^$U E0FikPPyhe` diff --git a/docs/components/odt/en-US/actions/End.odt b/docs/components/odt/en-US/actions/End.odt index afc6dcea25d403f97e9c7be2d317be8ecff1187c..83824cab2e6fc85cb7b6f17ba1ac397e2fc6b1e5 100644 GIT binary patch delta 52 zcmdmUk7dt27M=iaW)=|!4j{}g*~pX4$CO{vT*NT!RX5l E0EMUyxBvhE delta 52 zcmZ4ffMxju7M=iaW)=|!4j^nP+{hEg&(u=boWj37g`d${63CvuP=nDNNN>NT!RX5l E0E^NO00000 diff --git a/docs/components/odt/en-US/actions/FileAppend.odt b/docs/components/odt/en-US/actions/FileAppend.odt index 2c6bf22210dbc3202b8c66d00f755396c865c5bc..faeb32746538964459ea53d71b9d74e35bee3f8f 100644 GIT binary patch delta 52 zcmX?ckLAQY7M=iaW)=|!4j{}g*~nAQ$CO{v+{(ATm5 delta 52 zcmbPqpJmd07M=iaW)=|!4j^nP+{kl~kEx}w`8?nD^L&ifl0f!!9t}owAidpHgVC2A E0GRs@=l}o! diff --git a/docs/components/odt/en-US/actions/GetInstrument.odt b/docs/components/odt/en-US/actions/GetInstrument.odt index d5cc740dce87efa989a71de0892dbf415138c3c8..cc2af6d267ce559778fdeb995e39dfb9b0c07717 100644 GIT binary patch delta 60 zcmeydl<&tN>Sz17psd-{U`@{xDAZFS=v4Qzq#^zWd zlf20WLb~noFPXQ;zhsI222?wJ&wW;N5dHN&tK0PH4_GCqhdf|apS+`ifBLfrtOC=m d9r7M=iaW)=|!4j{}g*~oL0mnpxb`7-bJ%e;)%l0f!!0d+=mAidpFoza&a E0F=ZIvj6}9 delta 52 zcmbPsmu1>r7M=iaW)=|!4j^nU+{km3m#Mk1`7-bJ%e;)%l0f!!0d+=mAidpFoza&a E0GgK$_W%F@ diff --git a/docs/components/odt/en-US/actions/InstrumentRead.odt b/docs/components/odt/en-US/actions/InstrumentRead.odt index 75ba02ccc135848dba230b1e161558ed1ec640b5..6575699fabc19e390b87826def750e48e3dbe693 100644 GIT binary patch delta 52 zcmaEUm*x3g7M=iaW)=|!4j{}g*~lZt$CO{vtirclg^$r%63CvOsLp5(q_@vfXY^$U E0EJ`??EnA( delta 52 zcmaEUm*x3g7M=iaW)=|!4j^nP+{h!w$JA2Ttirclg^$r%63CvOsLp5(q_@vfXY^$U E0E>h($ delta 52 zcmezLm+jMEHl6@)W)=|!4j^nP+{jZUz|>OM+##^NLx9n08IV2w$TmiEAie$XHpZ{) E0M{ZC*#H0l diff --git a/docs/components/odt/en-US/actions/JSONStringify.odt b/docs/components/odt/en-US/actions/JSONStringify.odt index 2ae17242ff0c4e1813ceb1ec16d6ff78d04d09b8..1d3b48f0bf43970f81a6d2dda7a0e767a26c5f1c 100644 GIT binary patch delta 52 zcmX?ekLAog7M=iaW)=|!4j?Qj*~nAP$5c?#+{w4SlaJ9_63Cu@Or6mjNN@kI&gjby E0HIe8wg3PC delta 52 zcmX?ekLAog7M=iaW)=|!4j^nP+{jbS$JA2T+{w4SlaJ9_63Cu@Or6mjNN@kI&gjby E0H-Ps`Tzg` diff --git a/docs/components/odt/en-US/actions/LVGL.odt b/docs/components/odt/en-US/actions/LVGL.odt index 799cbca80208d623d04d19492a3ee6d634f0059d..64653eb9b64a385f0f17f7f53dd2379622fbe926 100644 GIT binary patch delta 6281 zcmYjVWmr^Ew`PV$kQ^F8K)Qz^MM8%LK}uRWq+aMFAC!1O@A{Ik?2&K8MfMe!b7gmpB?vPoDWv zh6INV_gaY6DOrPKcRRtJu!kJFA5bG8@Fj|+T%mV?cd+*lPL!NCa&d2TtBgfUX_0T{ zDHkHkxl#IPA6_X4)nVi&k#uBE?PH+5VPRleH9EYR*qN+cJ|KJR6Sv0u#E77eM?oS{ zlO+gX)XT9Vg%9`I=IM5>>wsDSDvh9*t_pPOkFomWi;jZ~p`>y?G#5`48rO15|4|)aZ zOzXV~)ZKR?|BCijtgi0#};4RzjKZ7dWu z7v$_GBKI+Fq`H31j-6Le-F$h+)r*Y01-j*2G%Qp`Jv2=k*H`wb^P*ap%GFlN$$He% z<0Yx{!Yh~d&P6H%YnEq=&ief;aDVAio{2WQ=lVqPk2y4Ok5;I2D`n+Kn1 zom;3sX2AM6-~CCsr4K539a#K6;H&7eYB?*@P_de-aOrlkh_NayXHGHu|Ch0#{f=L|!;q6VEi4Fjj)((_a{qRX2At z{k%E@&3cCc7j-zjKg9ykxB&C9ylC?9ifeo$ybIbc%KbIUX5J15ys71}?bq)+@}rIM zGFJajnt7Bg{z@zVq=VmMA$XDUh1nI^+c_+s9 zEHGE!WvTHTqc;Cc8KRiKbm7V3bD|dlqEXzgddK{~7wK60Zq%C&I^n3r4N*2sD!6d<*Y{yYz22z5sV5 z`I3fwEVfu^CG(u{8Su!9bPC~~>=AFgC_WSW5?rqj78p9c{*}RH)4VptF-$Tq*RqF~ zw!N!CDb8XsO9Q3(Zb?2(o3VIz^jn{sHZ#KKKn$-<;MjJJ6#T_T^Sx%W&G}6hxsC1D zrsY+cn$wRY?Mh24@ea-05FNjGk zQ?$vhW^T`Ip=E!246zS?2+`WS8`~^TZ{E7bzRL4qOV*|>tIcDEpUcuQGK7XJ@bgnZ zcyM#vnXS}wT@*C5ovzw(#HZ5wxP*0#4z_+oN$qMxyrUa0*NpLTI3l`@;b!Wxt5+yC z&d7to6dm2j*p=8db?b!(qJwxFE>ZeZp0fJNLWv4}-}@1yN%eMfF!EOsPwaW6y4Zf9 zVRv?pBzsxSlpanIj&kkRXnp&gskzrx%z&1e_m|j9Y0^3 za8^HCmagmxleI;x!jNHeW>gDHFHdSeDYhE2yCorZe?^#Ocsz6XD7dGfpxsm!m%6W3 zecal56=mcJ=o4%E*bnY4jTV4ep}WRc`LC40i?fL{30ZF7wx;+idR~JoMqxOf{C2in zqONvn3Wk1JcMG@+13z`1)I2qPweTcKu&YygWsiWP$yq9yaZ4GiAuL9yRDdX763jR~ zk}G%?d4}jAuLI%-RO-K4;S_yaSm0agOOEZ zv#EB)$^Bp&NipvM(>a|2DavqI2VOl)uiu1Qd+sw#&x=iWrhGWTX#0Knf%uUojaik5 zev`16Ct!-0k9+N?+l=~5&0QQHN*djFl%xe0edXMlz4o7XUebeMidV+BwUcV<43Fxy zfDb1iYFf0Eo3+cqpGU&=Yim#IwM50su>7`U4Wics=v5f>9!8XMn{`+|j~hHL)z^9=UWYwNkSy4jk#x`=a)-&$#6 z&QR#Dh#~@`=I4p|Y#jLm`*(5!n4QPs0uxu(S^bF=q8LAJP2t}rsptl_3>vQRpJ+=9 zs6b7x>2eMWa+EizGp?T!yR-_K~GmmnoAok{_`=bU!k@eTwQEgqs-Hc7qXE2pHo2o9W0Ta$qW(th%=IJ#LZg?J+S z1LsvsWYcepYQLg+ULXm~`1|t;a76Cih!m2g2;h8&5!1gSa5VhN3n1uww zqEgJND&Zi4J<64vG@t$k$86pPTeUa6^Gl)dN~=oF|vC3yJ#W=owlO{tb0BFFUL5_H-UOBV;5#9`6tybX-%eXctqX8V+8Vq zR($@BG5Y$?8l4A#Co*_x+{W1IGwK6dENb@y$?w0MMSi~*Tps_vbJhqUSHULEBoofk zr-`(@ocVs}97OnB{S9QUtSwUpF0NEChjpY*TCTwA-$YFpU;IW!=Xh}4;)5#{B!>{s zgS{%tcnIt+YS1_rk;j@r_LknT7KcNQ&UhRpBZI&SV%fjjx6$A4V$<6Eo!;qkXPCb{ zyA(*f!>}d5JcU25Sd_k?diXNe+<#@Au)Xi<+`%bog)ummT$z58H?`9NP6YM)$Bl); z{sB8|=6ntv#2eupmo9PzV~(&2MyF>cauF|7N&ZW_zy1TJ!U?G;pP9`)dA0|5lRGVm zzR9h>l#V4=%4XsDM3vT8tZI~em20&h4FGF$5zM^lZ-z}?h8@8f!-4;Jr#sO< zz|j+X&pDfNz|9>Jclp#Amzg*9(f9A{!hs!fe`%)!(LYdv%Ul>LY!l6_&x;X9u3{_^ zmfGV>gep&h{$C1s@fR#=OVn9p4)LB3jW!#ZE#D)hmTy<(n(F11x#8)%r7*{Lr98SD z4?k51RYB-!oJ|N3=6g>rhnps{^(jsDHpFh?G!8!F2vJ3K%6V>XiGh}`wz?RPL$k@W zfyBD|pcJ{#8>=LbKWi}awe#eUxqs8khE*mB29@(U*<+SkcT^zB#@S@6-=|a1<;>F1 zNE7aYZWbj~AIAzRoD>iBW^JrNe6i7!)IBTk9XS)9Wf%vA-wPA+X)T&kvbo^g-){qy zlA1?wEr8YqU6ORoEwOXe_7Pv0uf35hH8bII&JcR&t}94Pr; z``;XUTaCN!0Xwz#CF+vOl0|TVSifWoC{7%AD4`+(ex@ z5Bda?y|I%9glbYACrZcl|G5dMS2FnNu-aGg%5<GCX}Mbc>}J2p0#_K0)zVdffyGm#W4T449sigKw?|K7mQTy2qN=1A>rg9{$; z9rX}@@^^?oN z*J!GOePt>XmrAnws1P~C$w~EE)Q*fI%X{)TEp9u!LQiq6Gg$%M6er4MuEsMvg0@=~ zl3;y6HvqFjq!L zo>;eI19EddQ7gBuYzMHQ9tck_Fkjd&`%SIX%zje7XiBwiBd5E}TkQZ`L=&XU&kc zHsy;hdj2`XKh^Qvs?MI89o_s|IbD7iI#bQle?HH7;ozhP1na@K>ID*3e(W$h&b`fA z!2ZFWx6VQOvB!S4WJ*abldZ+dh;1)e&e)!eoreC0V7}$Do!f?~t8jh5+mt&+lGf(* zghiuBihFWa5t@kjAa4=XhUTd@O%uQ!Rh&bcF<$bIW89kAxoFMfi zt*8Q0f1cRFYXafn6l+7q55SAfB4dDSJxJb%G(I?-o!^xs4xXN)+8EuKAPbhjn7YlB+nqH?%Zk^!wm61q{C`47KmQPs_Ty3Es;X#HEzr z_q`ZIDa-io{-XzNAGPkJV{mzOEWh-YXSOT$0aHZ*6YHb=I-VUl3W`%20OkMRsRxvj*OZb2L@Dqb zT%@)C&kJ$J3*eyrE7kk%2|vc5uwkO0fKdMTp+m{>%STA?0i=K-l(A`)42XO_02@FM z@rw^21~5YqfB|xVjK78!;Q-j@X) z2kA$U3O*WEgrXoo0H`8`SP}$K#`;Qu5S4aXwS$d}m&rIcGw*mlYC^E{I>W}wn;i=@sbzkk{b>9(rDn-E&65>K~ zbxT<)L5-#{448#DfglTZl2hS>P}ZCWth57UisMc?l~UE#QcPj%K@LJ&^{wtHGXebk zLa!yNUyII9J`KV%+c>3XR4V#AfsCAKr5bLb8v(n;*>WYTsS}pv*nL4>2okVLD z7td@cDsnAZg&y?9P|_K;$OkqRr`tuhrahenh`e=Ri`(@9nVvV81Qi-(6|K;$fh17z z{BB;vv&xo^cxR2TuiM_5{|GCcKU(8-o&dZMS zl3J|iTORG=lWRC@qh_8TD5y6xphS-F_EisjTJ7oX0xJ5v?BOL=*xyay?)LEaNA9-5 zHoASVk>Ezu&Irj;s593z7oIhBK_mE=PvCEL3_4f3)yFcOcVtk8+%m%1TWlWIx?HOi z>mlBW>A7qlvI1Qsc|_a}#!=49e$^O60C$;)uA$CM>eK7(Cpyvcig(UeP91>_{Gryh&n#<*?6?*Ht16C;xEuQWrU~DQyTkcY{+c`JK1@ z1e5+?pV&o*Fm`r%?U*2b?Hcb`6sVs?S}`)|$@5Y@ zxeH5m-CyZ{xWmg8!pe-^CP}P3t>R$)S|3sXGVuGz93yG5q%*40x>A_8FL2oef%#Wi z>ONZEc}LdEmVllPt|Suy7>0=gTHlqSez@gprk3YbDSf6xQOiINyvg4CM0iq&sH)y= zhJm3y+g}}vt-JB6ife~?I0ISJsF6B7-5+*5CLKLthLN2$`6m?2>tO++UUO~V!?~P3 zsu$)EU}QFC)C?%UYCq^x7VQvxK(@z_JN~g@&es(0ZesR^;Lr0yK8Ovch|)|qIOij+zF*KrLpOxgGj^! zqs0TQBXWsmRwn1H$9~kZ<@VVBx9RYubkM^4;$%)5t~6+LXfkI2YuAm#Zko}2dcQ~tuf)~i$=CtAVG;I&B(UhU5sC9@-_gY-f-6aCrw&*G0cTa5Gv zB_Lr2MJeUKzB`CNd!)N&^IGjyxKrDyu-B>8`W}}{PTn?uu4YRC<+^*AlWb-eK>Lo^jS^#%XdlxFmC~kekRPMhB&M8`gebST$1$ z|3yzym|V|=&yEk#coz~n7C1==C#^Z!LctrbOktk=r7-YsQ;R*~T_V4@kMzSKJ`-(o zzZwGgp076ubavF4`Hg35hnHM)Sg<-r>Q6Hrj%pMeS~x!sNb1M%>9u~9r=}sK*GuI ziV0Sz2i@X9QjcQRiJ6%~cCb5UW6mT-gt%UN z*J%o-J^N~PY*Iqh0 zI!&_Jcb`=#(lkT%Pg)jVHZH%uYbjc8_q@Aa?vy^r?(n@?9IniM@Aj)G4|)0{+Swmw zm4GQP7+TzlD!1 zn4N%s;MOTNO*zI@V5G@v-SO!*Of-dp|u*7qTUy&l3`C1!|%D zVb$qWQIk$g9yDNu&>J&rE`n)`ap= zjEO#wJCp2T@91qhY;L!5jW;u+yWZ&1pxrR&%h67U`5+q!2^vL0Y^_?)C-$)msOCn}&F+FBSc< zVY;P}xK3T@Y3-~kFjP|TN}Ta6)ynuak!~oH+1)p-+zt~Q zu((*impkX-2G8oSl&@$c-}%P0r0=K<3+&5sqT$}yg`i>vlOH&15eE`ieN%+j++i{V z78maKaw?VGRuv=8zPWWG;tPR0y7qA5k&G_=rtF|rEfRzyn3 zBLg{z9pdr9S$mPf{e!4jNZeqU()bl!V~jb6;pUDd^Xr0&5|(cuue7=B()WjD!rR^t z9TgTJP)u9Mb8^|{l&*_yvEQWVny(V{XWws?WqhWRq$4zvC(<{N9oF!XdO%5#u}|~- zk03)AE$9V|b{J%}PjAJlZwQQFcJqa$^e`E|Ivo#vX!eMnXF+U}X@QpXCHHXRqf4)Y3J0R1I?FTx_9L=XD5%1t zupYe~fL!ARawMGv%kewI+RCN!Mt(bt}9 zQ|Nmmb~+lt4$`o#cVlMg!v|!r zB4HnGXa-9TTdVftd{JlSF}hZRd<-%}D5ibUuxl)Z;g!yAzpw(k8tjysmxgbmaO}bZ zWoV{lu=xEEvyIN;%(_1)h?9_bA^e6y7EG{n450W4+EF=Aeu6cm8!A*?%R6hhBcJ(7 z+HQscXX>SfjsS@1f)+opIP&s?`waP$eOfFZ+A5GY4PMu3X_1bv$C;!Xso|jO18w@r?9&!r9L6nxS<#CYj4A1IcE47@WgZoZ)>#lVN3<;>}*l7Xci|yWKA{5 z@shl4yAS^2fDmAS*Ca9B%%b-NlAAGH;+#4k{%Tg(PCb3v!unVg3afvj3%Xu5cUOYs z)Pu%plI(ytHqn3{QDzpWN~%PnKsz zDB>~O?F57$UYnh+MdSqf(XN4__i3UtUYI`P`^`@I`#~p~HjuI_M<8e#;NB>c@gvz% zS)Rk77qdfbWxsLd4{VMSGxJN9XNl&99&d_qK!=6LCJtnoc)>6u8yoaw=HTQjRo8YP zkGVbHTt#S@$0#^VS1~R2g_(^ZqG&I}2Px>KMEsNMN&i>ky?~6~|3uy^zlXsg z_oV35o-^MGa%{kCs@^NPjz-;O@ipBn;U773<*jIVYr2F#NV1Qb z{ol;8tb)6go=R+4z=e;&Q_}7U0c~F0h~%k`PLBE|e3;j@speHUzc1}@V&P2kmLQI^v_g8XF zN2{ik=G-RfIwSYdeSKf^kgFe*ut?J})l!$v`xVA--KzC*nj4076{f`dV&oksyo4t+ z`FI2NK1~xDgqMd#;z<$g__%K&A9dli_(jwVI&R-)o&CGdQhM#x3H7+W%ghX*<6+%5v5kO1!HKn0wPdRfs~1WH^E~+g6`NwKP8M;Wo&rKfX<6C`saA?~!dB zbf$qyLZ;uv&I#klM`ebgCab3_w1Pj$ARCz1Gr6eVqJ!p_N(LmVUow-PoqKkPG<#)o zr#*7)_vzT{SlH7@53rcy7MNgLr@R*a{tbn0I;y1<4ow~J=(=1#^MuN?hrb!~6<>gr zkgGHYL0Z5X{pSS&T#GyOc7+x>NM)hLu`LC=F=&3KvV=Jbs!=6iN>HDuh{Dhuok)#J zGL{_VDRpz;A(~3->)vOmGM&yk5~8kl6yp@hLmL=RWb#`AC~;{w950qD>;EOW-2X@i5? zNmW%igH}vP&^E(#QmY%6TwuK!Y`L&{8Mt8O%Zf8wKaM>?DmZjB{SsF+!E}9R+wru# zh4e1RClywG$Tub@`{2jeHw~w5T;OAYKMk}yLDw?}eG$`(l*W^EDXu-v8)o@abu=S| zV!A_&X*F-zU-@MDxv7-tC+B7*Z#&2JyldN>mO8)bw=b+I?NIcQ1U;IL2dquRjm1>9 zL)T=oFR(42Eq$!vxPteI%Gg+1bGl|rh^7RHd#PEg*T?)4H6=5(@eW36>A1X1fn0gC z;x?uepXm~e~|N0!G(-h zZSV^Uc6z>Da?$TI6r`a0e}0PL*5Ij+$u}`l3v5!XHOs?9xHKgrNr0Lt?et@DjRtc` zV*9`;gr7IulM)Qz!iy-GU^91ex9o2LApvqImH& zoy^G6kL?aqj}h6hOMzrv*4?wsgI)e(pQ|Dv*kwtiOyZ4%!u2^@158lJ0c{*jnjfPn zxO;Vup0w%V`shQUxAu+QU8a(^Ih!Vn^!jej6c*R{YAqe}3n8*oJ221AlJ-6NrMSLI zANqxTAgJG8Ip=1L-eR(=R`~gqkYTnwmd;&lA4Xu#mwkJCNz-S;KFcny79Jjs%=wpn zwSC`IBam9z4M#l=l;3V2>u5Z{>Hjlz%JKpqG|LvZ<=-(qf<)v##3n*Q1b_fhh}VD3AfieH z5V;SyDFO%sy$D*-d&7j#6$M1l)#VYgVgL<1LY^GaEDCUDzryZ0r9_$~&B0xAds2p|TyBa|Qj7xsbxaQ{I61G;40-~a#s diff --git a/docs/components/odt/en-US/actions/Label IN.odt b/docs/components/odt/en-US/actions/Label IN.odt index 3deaf268e8b51446a330197636e93efe75ba9a64..9bb944332286880e829bfd0dc6ee3266cb9aae37 100644 GIT binary patch delta 52 zcmex&m*wAG7M=iaW)=|!4j{}g*~p{I$CO{vY|Xdbnvc<163Cujq0VRyq_=NWXY^$U E0GAgIjsO4v delta 52 zcmex&m*wAG7M=iaW)=|!4j^nU+{mNL$JAWdY|Xdbnvc<163Cujq0VRyq_=NWXY^$U E0G#R$(f|Me diff --git a/docs/components/odt/en-US/actions/Label OUT.odt b/docs/components/odt/en-US/actions/Label OUT.odt index 2da5f5ab85c576a977d3dd03d4f14dda1a76bf7c..b21e6dd41056eebeff91b5f3cef53515c1f2870b 100644 GIT binary patch delta 52 zcmex&m*wAG7M=iaW)=|!4j{}g*~p{I$CO{vY|Xdbnvc<163Cujq0VRyq_=NWXY^$U E0GAgIjsO4v delta 52 zcmex&m*wAG7M=iaW)=|!4j^nU+{mNL$JAWdY|Xdbnvc<163Cujq0VRyq_=NWXY^$U E0G#R$(f|Me diff --git a/docs/components/odt/en-US/actions/Log.odt b/docs/components/odt/en-US/actions/Log.odt index 88640bb75781a34ad5c6a4a976b9a179f3261fcf..d7df7f6150571d74420109a4f4eec10ea176bdd4 100644 GIT binary patch delta 52 zcmZ2>k7e0C7M=iaW)=|!4j{}g*~k;h$CO{voXod9nUB$063CvuK%LPXNN>NX&gjby E0E5B~r~m)} delta 52 zcmZ2>k7e0C7M=iaW)=|!4j^nU+{hEk$JAWdoXod9nUB$063CvuK%LPXNN>NX&gjby E0Ev|j>;M1& diff --git a/docs/components/odt/en-US/actions/Loop.odt b/docs/components/odt/en-US/actions/Loop.odt index ec36e8582d63c9ff7e067726ff893f06e67ab0c1..c28d45d03a8d0b010b2bc4f765829f97fece7323 100644 GIT binary patch delta 112 zcmZ3#j&1!qHl6@)W)=|!4j{}g*~sH1$dq5QIYRI$3vZC$ymk8K??B<{ zS^bRWAbN2>qvLer35;^0#=;B?0h!4qrA4X5`Z@Xe1$qT}>C^ delta 112 zcmZ3#j&1!qHl6@)W)=|!4j^nU+{oi4$kbf8IYRI$<7V!PRq~t7h0mpI-a38rccAd} ztbRsw5WTpc(Q&%+1V%X~W8ulN70T0Z^fPLSJ~m=t2*^w>DJ@DZ*3Ze$FVHK|kDt+663Cw3t-)vxq_-c@VDx1N E0Cf=#A^-pY delta 52 zcmbREfMwzX7M=iaW)=|!4j^nP+{oj=&(u=b?8m>|kDt+663Cw3t-)vxq_-c@VDx1N E0D9yOW&i*H diff --git a/docs/components/odt/en-US/actions/MQTTDisconnect.odt b/docs/components/odt/en-US/actions/MQTTDisconnect.odt index a7cb628470d318896a7b15bba4faeaa279b65aaa..814be23def7acdbc5739754fb3b542e83674c7ce 100644 GIT binary patch delta 52 zcmaEVkLCS67M=iaW)=|!4j?Qj*~l}GkEx)fc@5w8HGGWLl0f$Km+Fk>Kzh592BR-K E0JlmHtN;K2 delta 52 zcmaEVkLCS67M=iaW)=|!4j^nP+{iPJkEx}wc@5w8HGGWLl0f$Km+Fk>Kzh592BR-K E0KFX#@Bjb+ diff --git a/docs/components/odt/en-US/actions/MQTTEvent.odt b/docs/components/odt/en-US/actions/MQTTEvent.odt index d207bb8e4dc096a6c53a761d554fa6f6a576e4fb..2cb822e047842484538c0f4e7c4cb7bba6b676d3 100644 GIT binary patch delta 52 zcmaF=nC1Or7M=iaW)=|!4j?Qj*~lX&$W&0$tRuKxN08B463CvOsl{jxq_;29V)SJP E0FOovL;wH) delta 52 zcmaF=nC1Or7M=iaW)=|!4j^nP+{hy*$kbBUtRuKxN08B463CvOsl{jxq_;29V)SJP E0F@aIhyVZp diff --git a/docs/components/odt/en-US/actions/MQTTInit.odt b/docs/components/odt/en-US/actions/MQTTInit.odt index a1b15e55ba0a47eb771df78039ee5d69842b1bed..5245d390fb309362f109b924df42a92c9dd77aea 100644 GIT binary patch delta 52 zcmZ4ZkY(XR7M=iaW)=|!4j?Qj*~oK&pQ)gv`5yoFd;E;nl0f!!X-!6RAiX_AlhKzQ E0H4$k761SM delta 52 zcmZ4ZkY(XR7M=iaW)=|!4j^nP+{kl*pQ)v=`5yoFd;E;nl0f!!X-!6RAiX_AlhKzQ E0Hvo7S^xk5 diff --git a/docs/components/odt/en-US/actions/MQTTPublish.odt b/docs/components/odt/en-US/actions/MQTTPublish.odt index 3568217f6a153f02e40034c6efe847e7f7cf11e3..41012b9932656d6e4f9fd689ffc5a67d66f13aa2 100644 GIT binary patch delta 52 zcmcb6kLB(?7M=iaW)=|!4j?Qj*~rtw$5c?#Jd1DpEIvkSNg#Xrb#+E_AiZ5cgVC2A E0I6^fE&u=k delta 52 zcmcb6kLB(?7M=iaW)=|!4j^nP+{n|z$JA2TJd1DpEIvkSNg#Xrb#+E_AiZ5cgVC2A E0Ix$2asU7T diff --git a/docs/components/odt/en-US/actions/MQTTSubscribe.odt b/docs/components/odt/en-US/actions/MQTTSubscribe.odt index a4de6b225d1b76db5f8159ced064c205c4c0d720..c1ac7f31ac0ba4032ca4ab79e96ac35939901696 100644 GIT binary patch delta 52 zcmZ4dh-L937M=iaW)=|!4j?Qj*~k+lz*JDuoFK40L4eU(63CuDSCi2kNN>NU$>_@t E0E7$@~ delta 52 zcmZ4dh-L937M=iaW)=|!4j^nP+{hCoz|>OMoFK40L4eU(63CuDSCi2kNN>NU$>_@t E0EyoY?EnA( diff --git a/docs/components/odt/en-US/actions/MQTTUnsubscribe.odt b/docs/components/odt/en-US/actions/MQTTUnsubscribe.odt index 6842a11742f24cf2ad35ebf0572c5b4fc040b057..7fb9ef0f20f8c64cbdaa20e8dab7d8d483a5f808 100644 GIT binary patch delta 52 zcmbP#k7fQn7M=iaW)=|!4j?Qj*~sI^$5c?#9K*LghL6!&63CuDQ=QQqNN>NS&gjby E0DiU(djJ3c delta 52 zcmbP#k7fQn7M=iaW)=|!4j^nP+{oj{$JA2T9K*LghL6!&63CuDQ=QQqNN>NS&gjby E0ECGSzW@LL diff --git a/docs/components/odt/en-US/actions/Modbus.odt b/docs/components/odt/en-US/actions/Modbus.odt index 98f28792cff267edb368439c22a3773bd579efb5..ae3c8c833490f5e5130c2f356978b7865f00ac5d 100644 GIT binary patch delta 52 zcmbREgk|Cr7M=iaW)=|!4j?Qj*~sG{$W&0$>?gS0Pms}C63Cw3t;J{#q_-c@V)SJP E0C!UkGynhq delta 52 zcmbREgk|Cr7M=iaW)=|!4j^nP+{oh~$kbBU>?gS0Pms}C63Cw3t;J{#q_-c@V)SJP E0DUG7cmMzZ diff --git a/docs/components/odt/en-US/actions/NoOp.odt b/docs/components/odt/en-US/actions/NoOp.odt index 52ef8e1f46fcfd83d8484e6a7edb76e09a52019b..b166010b3e949bf49b533a927a5d1a20eeca97e7 100644 GIT binary patch delta 52 zcmbPmmu13T7M=iaW)=|!4j{}g*~qh>mnpxb`7H1Dv%HMfl0f!!E_Ft8AidpLoza&a E0FWjQi2wiq delta 52 zcmbPmmu13T7M=iaW)=|!4j^nU+{m+^m#Mk1`7H1Dv%HMfl0f!!E_Ft8AidpLoza&a E0G0U;%>V!Z diff --git a/docs/components/odt/en-US/actions/OnEvent.odt b/docs/components/odt/en-US/actions/OnEvent.odt index 2ffab79dd10659f4bafb33a54b12e7e8559c4151..dc3aefb2ed73b1e746a06723db910f125984eadf 100644 GIT binary patch delta 52 zcmezJfaS{r7M=iaW)=|!4j{}g*~qh)pDDkjc_aV!jr@$(l0f$KcN&c5Kzh5nCZjJq E0K4rE)Bpeg delta 52 zcmezJfaS{r7M=iaW)=|!4j^nU+{m+-pQ*X9c_aV!jr@$(l0f$KcN&c5Kzh5nCZjJq E0Kvcz7ytkO diff --git a/docs/components/odt/en-US/actions/Output.odt b/docs/components/odt/en-US/actions/Output.odt index 0eed7acf976c68a3139dd07e72d4d47699fed742..652c68dd3e718fb7726f32e3decb41e989e824b3 100644 GIT binary patch delta 52 zcmbPmmu13T7M=iaW)=|!4j{}g*~qh>mnpxb`7H1Dv%HMfl0f!!E_Ft8AidpLoza&a E0FWjQi2wiq delta 52 zcmbPmmu13T7M=iaW)=|!4j^nU+{m+^m#Mk1`7H1Dv%HMfl0f!!E_Ft8AidpLoza&a E0G0U;%>V!Z diff --git a/docs/components/odt/en-US/actions/OverrideStyle.odt b/docs/components/odt/en-US/actions/OverrideStyle.odt index 8178f2086a9b06a45bdd7e5774cbf91992fb4012..168bdb72d773ebc0b8c9d831f9ebfcc239ac51c0 100644 GIT binary patch delta 52 zcmdmfmu3517M=iaW)=|!4j{}g*~s&Zmnpxb`3vv%FT9M_l0f!!Lv==TAiX_Hoza&a E0In$yng9R* delta 52 zcmdmfmu3517M=iaW)=|!4j^nU+{p8cm#Mk1`3vv%FT9M_l0f!!Lv==TAiX_Hoza&a E0JHoL-T(jq diff --git a/docs/components/odt/en-US/actions/PrintToPDF.odt b/docs/components/odt/en-US/actions/PrintToPDF.odt index a66147b28e41fca3307a138fab57d0b3e8cbdc87..69d655e12d758375b01bef4adbc7de2b6764a61a 100644 GIT binary patch delta 52 zcmZp8#M1DHg(tw9nMH(w0|@g=HuC5TFy)st+X`&A6=1ZM1hS`BX)>Av>Ft{}8GYFS DXvPh& delta 52 zcmZp8#M1DHg(tw9nMH(w0|;9RH}dEUFtrpm+X`&A6=1ZM1hS`BX)>Av>Ft{}8GYFS DZtxBG diff --git a/docs/components/odt/en-US/actions/PythonEnd.odt b/docs/components/odt/en-US/actions/PythonEnd.odt index f957e32846f124ede7da605674b6cf3424e794aa..9f47de3de3e9207569fd38bc56227567d61520d8 100644 GIT binary patch delta 52 zcmbPqk7d$57M=iaW)=|!4j?Qj*~sI_$5c?#?9aE|pO4X663Cw3qt0j!q_-bcXY^$U E0CcquAOHXW delta 52 zcmbPqk7d$57M=iaW)=|!4j^nP+{oj|$JA2T?9aE|pO4X663Cw3qt0j!q_-bcXY^$U E0D6cHWB>pF diff --git a/docs/components/odt/en-US/actions/PythonRun.odt b/docs/components/odt/en-US/actions/PythonRun.odt index 508912dac9ec0d3406fd6fe80a9f1c0dc441a11e..a5d975aa8b9664fd63ea9ba416a76e2e9c0ca3a9 100644 GIT binary patch delta 52 zcmbR7m}SOe7M=iaW)=|!4j?Qj*~oKTfT^IQ`KrM7s{)MHl0f!!AuUF8AidpNi_w=I E0GbF6-~a#s delta 52 zcmbR7m}SOe7M=iaW)=|!4j^nP+{klWfT^Xh`KrM7s{)MHl0f!!AuUF8AidpNi_w=I E0H50rBme*a diff --git a/docs/components/odt/en-US/actions/PythonSendMessage.odt b/docs/components/odt/en-US/actions/PythonSendMessage.odt index 063636560e3abc5370c5425ccc5045b8fac55308..c775e7602a9eb682554f8ed4a5fb0baf36b5517d 100644 GIT binary patch delta 52 zcmdmepJn%b7M=iaW)=|!4j?Qj*~s&XkEx)f`3K+jAAF3~l0f!!Qw>IQAiX_LgVC2A E0J60Y!vFvP delta 52 zcmdmepJn%b7M=iaW)=|!4j^nP+{p8akEx}w`3K+jAAF3~l0f!!Qw>IQAiX_LgVC2A E0Jw+{2LJ#7 diff --git a/docs/components/odt/en-US/actions/ReadSetting.odt b/docs/components/odt/en-US/actions/ReadSetting.odt index 8e9d49e6dae74fc66b9fa33ff597846b5cc0a3e8..0c487e83040f7a0bc3cc264c980e4eabdb15e7b7 100644 GIT binary patch delta 52 zcmZ2-pJmB?7M=iaW)=|!4j{}g*~oL5k14;T`61u-hkT6Il0f!!ISod0AiX_YgVC2A E0HCW69smFU delta 52 zcmZ2-pJmB?7M=iaW)=|!4j^nU+{km8kEyw^`61u-hkT6Il0f!!ISod0AiX_YgVC2A E0H%HqVgLXD diff --git a/docs/components/odt/en-US/actions/Regexp.odt b/docs/components/odt/en-US/actions/Regexp.odt index c40071fce50dfacf40a87c9a88671170a46fa72f..6139504f4adac3acc8df1906ee05c1b24de9c67b 100644 GIT binary patch delta 52 zcmbRClx5me7M=iaW)=|!4j{}g*~oKLkSV{U`Lf{l%Yuy7l0f!!0c}QeAidpFo6(mY E0GUV**8l(j delta 52 zcmbRClx5me7M=iaW)=|!4j^nP+{klOkg27x`Lf{l%Yuy7l0f!!0c}QeAidpFo6(mY E0H1OX9{>OV diff --git a/docs/components/odt/en-US/actions/SCPI.odt b/docs/components/odt/en-US/actions/SCPI.odt index 49b40f81834f035aacc4dbf5bc6afe1338cac418..45f8f66f781f82fdd05a67c5d4f02f44779c4343 100644 GIT binary patch delta 56 zcmccpkK^_~4xRvSW)=|!4j{}g*~rr%%#>f!+$Y@LC(O9LPnd~Q8OWbL(~QX+NN>Mn I#?;9H0QCzII{*Lx delta 56 zcmccpkK^_~4xRvSW)=|!4j^nP+{n`)%+ylY+$Y@LC(O9LPnd~Q8OWbL(~QX+NN>Mn I#?;9H0Qk diff --git a/docs/components/odt/en-US/actions/SelectInstrument.odt b/docs/components/odt/en-US/actions/SelectInstrument.odt index 95fbeb70d3ade8b8eaea83bd989853fdecd4c20f..6073183849e3c1b199cd4c6218420fb8dce15cdb 100644 GIT binary patch delta 101 zcmaEHo&CjicAfxlW)=|!4j{}g*~sI=$CO{PIg0N$<7QR^k3F0H1vbb}Prkq?wmJFD z-0wiS=}b=;%|W#F6Gq4Br=Kv&O`r9Ik$3vHCye^j%bqZ*FwHzOea;g`&F!jB84t4o E08{8Ef&c&j delta 101 zcmaEHo&CjicAfxlW)=|!4j^nP+{oj@$JA1|Ig0N$^Pn7x3FNJ^2Eo*yiLn zbH4-SrZYWZGzZbvPZ%Ai-+96)H+|LFwLp8GYFS DXwwa| delta 52 zcmZp^$I^U{g(tw9nMH(w0|;9RH}V+qF|`ynJMe9H;A6Cw1hS{ssxz7c>FwLp8GYFS DZv74W diff --git a/docs/components/odt/en-US/actions/SerialDisconnect.odt b/docs/components/odt/en-US/actions/SerialDisconnect.odt index eab2daf16134ddd4506e87ac54df6af32e04c0ad..70835261508606dc95f90ca0f13b19585839c222 100644 GIT binary patch delta 52 zcmca|m*vV`7M=iaW)=|!4j{}g*~r7p$CO{vEXcQAkdM(?63CwJr_N{&q_?-LGy1Xv E0CvRt<8 diff --git a/docs/components/odt/en-US/actions/SerialListPorts.odt b/docs/components/odt/en-US/actions/SerialListPorts.odt index 7512a1170d50cdc7c87f029234132ea84d54e9be..77d35419df6e56d9bd32580dcf885f794e5dbea6 100644 GIT binary patch delta 52 zcmZ2|k7e~e7M=iaW)=|!4j?Qj*~k;c$5c?#oWZv}gOAZ#63CvuRGrZrNN>NV&gjby E0EhAp&j0`b delta 52 zcmZ2|k7e~e7M=iaW)=|!4j^nP+{hEf$JA2ToWZv}gOAZ#63CvuRGrZrNN>NV&gjby E0FA{D6951J diff --git a/docs/components/odt/en-US/actions/SerialRead.odt b/docs/components/odt/en-US/actions/SerialRead.odt index ca16838324979340899c53503c2638e248741c68..4b8b4f0900d125b8539f2c95a0d2b31535230788 100644 GIT binary patch delta 52 zcmex=m*xLm7M=iaW)=|!4j{}g*~p{E$CO{vY{R$RhL6!&63Cujsm^E)q_=NUXY^$U E0GHejl>h($ delta 52 zcmex=m*xLm7M=iaW)=|!4j^nP+{mNH$JA2TY{R$RhL6!&63Cujsm^E)q_=NUXY^$U E0GkoZ~y=R diff --git a/docs/components/odt/en-US/actions/SetPageDirection.odt b/docs/components/odt/en-US/actions/SetPageDirection.odt index 8fbf4def189699f636e9de2207c87b1e2222bad8..08624df19c50eed7d521738b126cd9480da75b73 100644 GIT binary patch delta 52 zcmbPymu2!@7M=iaW)=|!4j{}g*~oKjqWd{Iv CTMh02 delta 50 zcmX?nm*wzX7M=iaW)=|!4j^nP+{p8Zm#L+&iEkSpqqQWEHQiR7(Hux`FH>jqWd{I# CJq|Vi diff --git a/docs/components/odt/en-US/actions/ShowKeyboard.odt b/docs/components/odt/en-US/actions/ShowKeyboard.odt index c211d8503f870800bbdc140a8f2bc4c49f474766..b8ca36c0b826d1de78635c9023595ebed58954de 100644 GIT binary patch delta 52 zcmcbAnC<>yHl6@)W)=|!4j{}g*~s&QpDDkjnN46jn*bwc7mz(&a2BIEklyY!i*YJD E0F|H*B>(^b delta 52 zcmcbAnC<>yHl6@)W)=|!4j^nU+{p8TpQ*X9nN46jn*bwc7mz(&a2BIEklyY!i*YJD E0Go3UX#fBK diff --git a/docs/components/odt/en-US/actions/ShowKeypad.odt b/docs/components/odt/en-US/actions/ShowKeypad.odt index 0f6165380a091b34d93244adc1d784c11540e89a..6d5e7a5d9423be5c49eaa1d33af76a6882485021 100644 GIT binary patch delta 52 zcmcb4g!SeTR-OQFW)=|!4j{}g*~sG}z?5Io93-$kNPyAO3&@_{8^vf2q_-c7Vw}tl E0FO=&WB>pF delta 52 zcmcb4g!SeTR-OQFW)=|!4j^nU+{oi1z|>sW93-$kNPyAO3&@_{8^vf2q_-c7Vw}tl E0F@yRr~m)} diff --git a/docs/components/odt/en-US/actions/ShowMessageBox.odt b/docs/components/odt/en-US/actions/ShowMessageBox.odt index dde586e67e6681155671dde2252d6312399f9507..9aec52a884463e6dc7450f22d8d11489b0a03d7b 100644 GIT binary patch delta 124 zcmbQ)#x}E!jVHjHnMH(w0|@g=Hu5ayXUZ?xypjJus;zF>jr PE2Wb|bR E0GY53qyPW_ delta 52 zcmezOkmcV)7M=iaW)=|!4j^nP+{mLVz|>OMY%Q?eT7c1763Cujp~+|tq_=O>Wb|bR E0H1>n=l}o! diff --git a/docs/components/odt/en-US/actions/TCPListen.odt b/docs/components/odt/en-US/actions/TCPListen.odt index bf842ef7d41c1fdb77f88fe95676c3646dc51bbd..32fbf54179d8eef37caed911f7579cf45eb84034 100644 GIT binary patch delta 52 zcmX?qpXL007M=iaW)=|!4j?Qj*~s&ckEx)fnTLNn4?m-|B#=GbQ-jeQNN;b_VDx1N E0Fy=zQ2+n{ delta 52 zcmX?qpXL007M=iaW)=|!4j^nP+{p8fkEx}wnTLNn4?m-|B#=GbQ-jeQNN;b_VDx1N E0GSyMl>h($ diff --git a/docs/components/odt/en-US/actions/TCPWrite.odt b/docs/components/odt/en-US/actions/TCPWrite.odt index d97ec92f0f3fd12c17252584887b8205ed12beb2..b3ce2c7d32fd9d605aea7ca45209a55af80a51a4 100644 GIT binary patch delta 52 zcmcb4m*wVN7M=iaW)=|!4j?Qj*~r7e$5c?#EXKE8jE~V;63Ct&tj=f-q__8|Gy1Xv E0DAQej{pDw delta 52 zcmcb4m*wVN7M=iaW)=|!4j^nP+{nYh$JA2TEXKE8jE~V;63Ct&tj=f-q__8|Gy1Xv E0D#C1(*OVf diff --git a/docs/components/odt/en-US/actions/TabulatorAction.odt b/docs/components/odt/en-US/actions/TabulatorAction.odt index 99def2bd65eb2764cdde659183efddaa0a3bca83..1d9de2895abaeb214a8ef94df76596517ca4f654 100644 GIT binary patch delta 52 zcmZpDz|#7Fg(tw9nMH(w0|*OBHu9M8GZmCHJMnLK;%Bs$1hS{sYcQGv>Fql-7=76R DYt;?T delta 52 zcmZpDz|#7Fg(tw9nMH(w0|;9RH}aV9Gqn^pJMnLK;%Bs$1hS{sYcQGv>Fql-7=76R Dai|Uw diff --git a/docs/components/odt/en-US/actions/TestAndSet.odt b/docs/components/odt/en-US/actions/TestAndSet.odt index 6823065dffdea71d5e44cdb9742c25fa7cd60efb..243a5b41f0a23a987d50341330900444cdcf76d5 100644 GIT binary patch delta 52 zcmez0#rD68jVHjHnMH(w0|@g=Hu5M5Fy)st8whMS5MXS`1+u4as%10>(%WCxGEQL! E0E%i4(*OVf delta 52 zcmez0#rD68jVHjHnMH(w0|=W7H}WV6Ff|u88whMS5MXS`1+u4as%10>(%WCxGEQL! E0FXTp7XSbN diff --git a/docs/components/odt/en-US/actions/UDP In.odt b/docs/components/odt/en-US/actions/UDP In.odt index 877df89448c9970937e3048bfbe89fa46adc3b22..0be33b0bf45afb6fc58de4f6176b914f2a41a726 100644 GIT binary patch delta 52 zcmX@~kmb-r7M=iaW)=|!4j?Qj*~s&epQ)gv`9J^m|NM;Bl0f!!8%;)YAicd*lhKzQ E0J%92{Qv*} delta 52 zcmX@~kmb-r7M=iaW)=|!4j^nP+{p8hpQ)v=`9J^m|NM;Bl0f!!8%;)YAicd*lhKzQ E0KW_nK>z>% diff --git a/docs/components/odt/en-US/actions/UDP Out.odt b/docs/components/odt/en-US/actions/UDP Out.odt index 7ed102baaba8e2414f17bc564ea6d1748df80c97..24efc8a14cd4d6bb2c6b5a59ce7cbab05e67fca7 100644 GIT binary patch delta 52 zcmbRDkY(OO7M=iaW)=|!4j?Qj*~oL2pQ)gv`8NOd+x(2yl0f!!2~9?GAiX_MlhKzQ E0G)*o0RR91 delta 52 zcmbRDkY(OO7M=iaW)=|!4j^nP+{km5pQ)v=`8NOd+x(2yl0f!!2~9?GAiX_MlhKzQ E0HatBMF0Q* diff --git a/docs/components/odt/en-US/actions/Watch.odt b/docs/components/odt/en-US/actions/Watch.odt index b51da71e7fe5c2f70db1e28d1f6ad947068492c6..0ce2fb04f729852eba8f3970e3cb73a33aea6595 100644 GIT binary patch delta 52 zcmcbAkLCV77M=iaW)=|!4j{}g*~rt!$CO{vJcn=l96m;CNg#XrO?5_dAiZ5kgVC2A E0IH)8H~;_u delta 52 zcmcbAkLCV77M=iaW)=|!4j^nU+{n|%$JAWdJcn=l96m;CNg#XrO?5_dAiZ5kgVC2A E0I+rsd;kCd diff --git a/docs/components/odt/en-US/actions/WriteSetting.odt b/docs/components/odt/en-US/actions/WriteSetting.odt index de08d65d7b026b6ea8b9146b4410fada877b5e90..4faadc08438deab6c6b630a429764eca0741f17b 100644 GIT binary patch delta 52 zcmeCX&(e3Fg(tw9nMH(w0|@g=HuCJ{W6CdSKFzoNG#{h2B#=FwLxa&ANN;!4VDx1N E0FS*6ga7~l delta 52 zcmeCX&(e3Fg(tw9nMH(w0|=W7H}dS|V`?sJKFzoNG#{h2B#=FwLxa&ANN;!4VDx1N E0F{sq$N&HU diff --git a/docs/components/odt/en-US/widgets/AnimationImage.odt b/docs/components/odt/en-US/widgets/AnimationImage.odt index 889929add2e73dbfbcff28ac9e7da38c3be4c609..4c58ceb2c1714141682e7302882e6e7cb93cb553 100644 GIT binary patch delta 52 zcmaDff%VY@R-OQFW)=|!4j{}c*~oK4jw!FC`I+4IXL5`y6@l#O6CD`Mf%NuM4vaI{ E0kgUh5C8xG delta 52 zcmaDff%VY@R-OQFW)=|!4j^nQ+{kl7j;X1z`I+4IXL5`y6@l#O6CD`Mf%NuM4vaI{ E0lAG4Q~&?~ diff --git a/docs/components/odt/en-US/widgets/Arc.odt b/docs/components/odt/en-US/widgets/Arc.odt index e6b7f06b0658405cfb355ac8417b157b91834b10..2b1f17ddb84927c54770cf6c567eb938687014ac 100644 GIT binary patch delta 52 zcmX>%h4tJNR-OQFW)=|!4j{}c*~oK5fhn(~`I5r+OA3rD6@l#OwN8xYKzjQ&C&n4< E0H&A_mH+?% delta 52 zcmX>%h4tJNR-OQFW)=|!4j^nQ+{kl8fvKsm`I5r+OA3rD6@l#OwN8xYKzjQ&C&n4< E0IX{e+5i9m diff --git a/docs/components/odt/en-US/widgets/Bar.odt b/docs/components/odt/en-US/widgets/Bar.odt index b10865e3a7a82419321f886cfc796b6dce35dba1..935f4f0c858833e355c936c906a7a62cac781147 100644 GIT binary patch delta 93 zcmX>zh4su7R-OQFW)=|!4j{}c*~oK9fhn(K^96;sjGJY&SIKYQt`yI)`Iy({??B<{ u)lQ7&AbN`vqvLc3XGS@u%}Ub~oEbHzzjtC(VM=zId|pX@d$Tj+Nj3n-c^}aL delta 92 zcmX>zh4su7R-OQFW)=|!4j^nQ+{klCfvKr*^96;sjGJ?vA~`m1SK1)I`Iy({??B<{ t)lQ7&AbN`vqvLcJXGS@u%}SH&o#dy#bYj$E64IW0UP*a-voqsKHUQ9;AS?g? diff --git a/docs/components/odt/en-US/widgets/BarGraph.odt b/docs/components/odt/en-US/widgets/BarGraph.odt index 92e7f16f4c6dd6d32ed5bebad792fae337e64cde..cc0c1abd32b880cdc9593960e9ad0b02613817f1 100644 GIT binary patch delta 52 zcmcb6hyCsycAfxlW)=|!4j{}g*~rr&&Xix$JWYK2G;zjN=YZ_#PR|(4f%Nw3XN-^7 E0mpO_M*si- delta 52 zcmcb6hyCsycAfxlW)=|!4j^nU+{n`*&eUAkJWYK2G;zjN=YZ_#PR|(4f%Nw3XN-^7 E0nJAeivR!s diff --git a/docs/components/odt/en-US/widgets/Bitmap (Dashboard).odt b/docs/components/odt/en-US/widgets/Bitmap (Dashboard).odt index cb3766e7e2607fd49131d6b421b8aa72901b2e34..bc98e424edb7b9e24beb53f5d73aa5906a6e5490 100644 GIT binary patch delta 52 zcmdmZn|rer#)pf2h!WmKV^Kx F4gl2J6N~@= delta 52 zcmdmZn|`IXrAS7MB-&H>rer#)pf2h!WmKV^Kx F4glJ%6VLzv 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 21e96bae8839164075e9caf2da2fa11e4e38b341..50da3e783914e0730d684bdea19ae462f996edf2 100644 GIT binary patch delta 52 zcmcb8o&EN8cAfxlW)=|!4j{}g*~r5t%9LNyEF!vHM3iyWIUsxbfya#IKzjSn$Bd8I E0i`t&qW}N^ delta 52 zcmcb8o&EN8cAfxlW)=|!4j^nU+{nWw%G6xgEF!vHM3iyWIUsxbfya#IKzjSn$Bd8I E0jmfR=Kufz diff --git a/docs/components/odt/en-US/widgets/Button (Dashboard).odt b/docs/components/odt/en-US/widgets/Button (Dashboard).odt index 17ff21fd14706bd0b9cf2163ba6a3860ac41bfd5..039b759c037ccca234b6e299f2dbb9aa437a062c 100644 GIT binary patch delta 99 zcmZ2|lYR9~cAfxlW)=|!4j{}g*~oKElqtVt^Api`>oyynT_wNy%#nDG=^rmJif#V* zX6|>O-1G@g7|lWS$tR56)8{{Blw&$^WcvQ6jGEK^o-(R1RXmwq@|00^`-`WHhuHud Cmn;(i delta 99 zcmZ2|lYR9~cAfxlW)=|!4j^nU+{klHl&QIJ^Api`>ozw%iR9RP=Ew&5=^rmJif#V* zX6|>O-1G@g7|lWS$tR56(-%Kwlw&$^WcuN!jH=W9o-(R1sh^!*@|00?`-`WHhuHu? CQY>Ep 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 95d5aa0b6bcfdab31ffbef292d68b0d5f49d8d38..4e6d8c7bd05e71b05554322f3a6758192145af67 100644 GIT binary patch delta 107 zcmZ2~gMIxCcAfxlW)=|!4j{}g*~k+m%9LNSIYaat4p z-0wiS=^{@U%|W#96Gq4B8c!MJrmuOz$UC{qUU+)b6Gkm2pCgkC#FeLC1hM}-o~&Rl Lzdh|K<4HCE={hRw diff --git a/docs/components/odt/en-US/widgets/Button (LVGL).odt b/docs/components/odt/en-US/widgets/Button (LVGL).odt index ee1c555ab0cde73e97ca90a46416dbb61264a5e7..f26b78e5baf2120866e2b45bf6c9aad83821dc5f 100644 GIT binary patch delta 52 zcmbQ;&pNxGl_$WPnMH(w0|@g(^b diff --git a/docs/components/odt/en-US/widgets/ButtonMatrix.odt b/docs/components/odt/en-US/widgets/ButtonMatrix.odt index 9d45658846192fa925ae4c1497121c89fd8583d8..c38b74f00175a857c266eca7350a97389379f753 100644 GIT binary patch delta 52 zcmbO~g?0WER-OQFW)=|!4j{}c*~l|hfhn(~d9lLw#R`lo6@l#Oeol<$Kze(-6XOha E0D^4~O#lD@ delta 52 zcmbO~g?0WER-OQFW)=|!4j^nQ+{iOkfvKsmd9lLw#R`lo6@l#Oeol<$Kze(-6XOha E0Ej>jkpKVy diff --git a/docs/components/odt/en-US/widgets/Calendar.odt b/docs/components/odt/en-US/widgets/Calendar.odt index 5808d50f6c25a8e1335914d95e3e5854e599f743..45f2e6054a400de632c1f72017b7b6a0c4fa001e 100644 GIT binary patch delta 52 zcmX@n&w8Stl_$WPnMH(w0|@gG38vpv{^ E0JB~Z4gdfE delta 52 zcmaFd$NIRBl_$WPnMH(w0|=W6H}c$+WojyHelENHxh&&KMId|nBzs14Aie#xJ>v{^ E0J$*{QUCw| diff --git a/docs/components/odt/en-US/widgets/Chart.odt b/docs/components/odt/en-US/widgets/Chart.odt index 1ec86560be16f8d8b8e10341ba731fe9103cd97a..cf574cbd4cfae566786c94a86c050e45be254b4e 100644 GIT binary patch delta 52 zcmaFV$NH#`l_$WPnMH(w0|@gv{^ E0J5182LJ#7 delta 52 zcmaFV$NH#`l_$WPnMH(w0|=W6H}c$&WojyHekQy9nJnWv{^ E0Jv-sO8@`> diff --git a/docs/components/odt/en-US/widgets/Checkbox (Dashboard).odt b/docs/components/odt/en-US/widgets/Checkbox (Dashboard).odt index 67a0919f9f54af694c1effd48ab212446f364899..bf77ab064bb28c19343046ceb732d159a9a3e01c 100644 GIT binary patch delta 103 zcmbPxgMID|cAfxlW)=|!4j{}g*~sG|%9LNSIZX5$<7Ss58{{|pi2qpA{N?fVFOL~{ zfHKpWo-mq&XzM48j?<4lVU(Lb>j@+8^p8&%Ri@VfxlEtTCdY}(P2cr|k!QQ;Q$`MU E0Mc3~&j0`b delta 107 zcmbPxgMID|cAfxlW)=|!4j^nU+{oi0%G6xAIZX5$j@+8WJz=3>6}j)d8XF@g_x|4OpX&*p1%JHBhPlx Ir;Hrz0BV{j82|tP diff --git a/docs/components/odt/en-US/widgets/Checkbox (LVGL).odt b/docs/components/odt/en-US/widgets/Checkbox (LVGL).odt index 7b655ab504135fe409685d762bd3b8b4e2a580fb..7d280af0324ab9f4c08105ca10722029bcfa3791 100644 GIT binary patch delta 52 zcmdni&$_Ljl_$WPnMH(w0|@g^L#6@l#O!48b(Kze(R1LF*K E0E7e&UH||9 delta 52 zcmZ27fpy6QR-OQFW)=|!4j^nQ+{iOaj;X1zd4=5e6>^L#6@l#O!48b(Kze(R1LF*K E0EyQRq5uE@ diff --git a/docs/components/odt/en-US/widgets/Container (Dashboard).odt b/docs/components/odt/en-US/widgets/Container (Dashboard).odt index f0bf97c4c067a6ce4aa1369c6df0b5adc3a7ff8e..5109a7ff709c98843ce519e585777b651a78fb24 100644 GIT binary patch delta 52 zcmbPxmwoPCcAfxlW)=|!4j{}c*~oK3oGGuQ`I`9lYvPQn&H>reo1QV61L^I%pD{jS F2LQ%E69oVO delta 52 zcmbPxmwoPCcAfxlW)=|!4j^nQ+{kl6oT;g>`I`9lYvPQn&H>reo1QV61L^I%pD{jS F2LQ|y6G;F7 diff --git a/docs/components/odt/en-US/widgets/Container (LVGL).odt b/docs/components/odt/en-US/widgets/Container (LVGL).odt index 08c79e98417d600c90514e4a7616282e8fe29133..651944fc5a0f7aa4ca72694a995da19cfcb0f564 100644 GIT binary patch delta 52 zcmaFb%lfpJl_$WPnMH(w0|@g~(%XIQ8E3Eq E0EC4Ong9R* delta 52 zcmaFb%lfpJl_$WPnMH(w0|=W6H}XWwGBp)8XUcBRlx1A02xLzev1c>~(%XIQ8E3Eq E0E$=+-T(jq diff --git a/docs/components/odt/en-US/widgets/DisplayData.odt b/docs/components/odt/en-US/widgets/DisplayData.odt index 9785631d097244015af81bf5d1307405fc56fbe0..ff8bd4ebaf45994f1d6d6cd4746025e2a422c09f 100644 GIT binary patch delta 52 zcmeCb#om95ohQJXnMH(w0|@g=Hu6}BG3A#udx&lK5Mx|*4#=MVK9ABpFf9&&+EY;(w) zx!-|u(?36EGzZZ-PZ+zWGd*RLW70k{dD$7|>8qbGYBAk@JpK9;M%C@!PZ$W70k{`TJw}>8qbGYB6=4nST8Vqvm$+r;LZ$07h^q AuK)l5 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 b680333c77c6caee90701857e05ef63e10cd1c52..f29c18f773092db3fb7d243d73048506d0e0fd5a 100644 GIT binary patch delta 52 zcmcb0js4a&cAfxlW)=|!4j{}g*~rr>!jxaqJXvJ>WD&+y=YZ_#_Kz9Of%Nu@$Bd8I E0l~r&7XSbN delta 52 zcmcb0js4a&cAfxlW)=|!4j^nU+{n`^!qi;YJXvJ>WD&+y=YZ_#_Kz9Of%Nu@$Bd8I E0mqdRTL1t6 diff --git a/docs/components/odt/en-US/widgets/Dropdown (LVGL).odt b/docs/components/odt/en-US/widgets/Dropdown (LVGL).odt index e723c906dc4d8bd23b0d6b23988d8cb7da09c3f4..e494de61096a15741b741247eada8ed5eadd99bc 100644 GIT binary patch delta 52 zcmeB}#M&{5l_$WPnMH(w0|@gu_sDPWk!M_~2xLz;cVsjN(%TCh8E3Eq E0B@NNqW}N^ delta 52 zcmeB}#M&{5l_$WPnMH(w0|=W6H}cfUGc^@9_sDPWk!M_~2xLz;cVsjN(%TCh8E3Eq E0Cj8*=Kufz diff --git a/docs/components/odt/en-US/widgets/EEZChart.odt b/docs/components/odt/en-US/widgets/EEZChart.odt index fcf81fd2f0857f0ee8cf861352f0731dad175892..1b8b47c8a149fbde6f8fb8987bf87f48ed2aa003 100644 GIT binary patch delta 56 zcmdmTfOE?MPM!d7W)=|!4j{}g*~l|fk}1EWdAVf!a!JPR%O#n_?122~`@@;cf%Ntt I;Y>Ch0N-X2SO5S3 delta 56 zcmdmTfOE?MPM!d7W)=|!4j^nU+{iOilBv0{dAVf!a!JPR%O#n_?122~`@@;cf%Ntt I;Y>Ch0Oi3EoB#j- diff --git a/docs/components/odt/en-US/widgets/Embedded Dashboard.odt b/docs/components/odt/en-US/widgets/Embedded Dashboard.odt index 97eb0ad8c33007a6fe2809e93e5e397247cb73c5..bb0bea8deaec902d9135e0644e0b613a41eb2646 100644 GIT binary patch delta 52 zcmaEGgZ;q`cAfxlW)=|!4j{}g*~rr^%9LNyJX3W0Oi{*F=YZ_#u1^@vf%NveCybBS E0mp$7N&o-= delta 52 zcmaEGgZ;q`cAfxlW)=|!4j^nU+{n`{%G6xgJX3W0Oi{*F=YZ_#u1^@vf%NveCybBS E0nJnrjsO4v diff --git a/docs/components/odt/en-US/widgets/Gauge (Dashboard).odt b/docs/components/odt/en-US/widgets/Gauge (Dashboard).odt index a88f0a69b5978979f3799fbde3e3bedc047758b6..3bb6a45a1e814fe49785b1b621bbcbdcd457e680 100644 GIT binary patch delta 56 zcmaEGfaAdd4xRvSW)=|!4j{}g*~s%%lqtWYnOUrzS&VTzvl!DSMj(IscX1|jAido{ Ig2{jb0MdC6l>h($ delta 56 zcmaEGfaAdd4xRvSW)=|!4j^nU+{p7)l&QI}nOUrzS&VTzvl!DSMj(IscX1|jAido{ Ig2{jb0NB(I*#H0l 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 de0f5cc73191b4eeb670b96c4f1bc7d1b221ca3b..a4fac727f7f54603aa93f02ff1906ceec9b96242 100644 GIT binary patch delta 52 zcmbP!i+%bncAfxlW)=|!4j{}g*~sH0#*|;u93ZwmK#XzKIUsxbpC^pwKzh6BQ^rT^ E0G(+OQvd(} delta 52 zcmbP!i+%bncAfxlW)=|!4j^nU+{oi3#?)Nc93ZwmK#XzKIUsxbpC^pwKzh6BQ^rT^ E0HZt+mjD0& diff --git a/docs/components/odt/en-US/widgets/Grid.odt b/docs/components/odt/en-US/widgets/Grid.odt index e4f69f3dccd988a91a5fbc1d7ff119ffd1a440b4..aeb069f933eb3c34a9eb1eda597a29aac9b31e07 100644 GIT binary patch delta 112 zcmeA>!r6C(lPAENnMH(w0|@g(7o*t5+iB@bJ+FS2CZzQ~ek zk33LrdO{?VIf$Ma$>ca)DT+yM`j1E^p~>rl`KKpFF=;W~4VvByq^IACWRhdL`hW6m MNtx}dqnMJ}0Y$PWF#rGn delta 112 zcmeA>!r6C(lPAENnMH(w0|=W6H}Y&1XKE_kd{~@~Y4iR6hb=dsloWf`zQ~es`yxxG zJ@P=g=?Rfc<{)}zB$MOx{3s^5=|3Wwgr?7rVv?ACE0Rf$sVR8!ZAtm*l2J@rObdD@ O{|u7bzB-C2nH>P7bSKjQ diff --git a/docs/components/odt/en-US/widgets/Image.odt b/docs/components/odt/en-US/widgets/Image.odt index addfcafbe4fb2068c2b78295b07fbca4868e2709..aacc218045f9c19d36670276da9aa5a03e09352e 100644 GIT binary patch delta 52 zcmcaTnf3N$R-OQFW)=|!4j{}c*~k;9z?4_g9IvoFUV(9?B9J|u%Zbq(NN;y`Vw}Ma E0Dv|QZvX%Q delta 52 zcmcaTnf3N$R-OQFW)=|!4j^nQ+{hECz|>UO9IvoFUV(9?B9J|u%Zbq(NN;y`Vw}Ma E0EP(;vj6}9 diff --git a/docs/components/odt/en-US/widgets/Imgbutton.odt b/docs/components/odt/en-US/widgets/Imgbutton.odt index 55f584cb0f11e068c1bfd3430fd70ac1beee0fd1..4febf37d1f85faf5c347966763300a6edc0b2b83 100644 GIT binary patch delta 51 zcmeC0$l5iLl_$WPnMH(w0|@g<7V^k5<&`w^$#3VAXI!ZWWKZAez-SJnw|{bAoWTwN DOa2ZW delta 51 zcmeC0$l5iLl_$WPnMH(w0|=W67xKt6H5E4V$#3VAXI!ZWWKZAez-SJnw|{bAoWTwN DQNRvi 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 fd01857a721377d042acaef677603137ddef12a4..18a9bce911f4f483d0553ae1f72198728538612e 100644 GIT binary patch delta 100 zcmaEQi~Z>>cAfxlW)=|!4j{}g*~l|Nj48il^E|P4>o&hWyGnj@+tGNA%~RiQ{tgtL z?)8+>97H!iW$d0F`HWF+y3R93-pL&2B&IVxW7J|YdOBV28Kdg-Yi}6Ew(oexxRwn7 D1=}f- delta 100 zcmaEQi~Z>>cAfxlW)=|!4j^nU+{iOQjH$VB^E|P4>o(gwjpW$ec65XM=BaNte+LRr z_j<}`4x*c%GImdoea0v^UFR7i@8rm*BGZ|kF={bAJUdL7Y7U~0aj-g059DN(W6BhtUdYL+ zF`XUAVLofkJY9p6Rdf0aAaDA1PFCLO!d$FU(jkpKVy diff --git a/docs/components/odt/en-US/widgets/Led.odt b/docs/components/odt/en-US/widgets/Led.odt index 78af652ea1baa7c7ad60198658caafeea4c7972b..2b3d68c07770522a627d52a24c4df95f0753eaef 100644 GIT binary patch delta 106 zcmX>)f%WJFR-OQFW)=|!4j{}c*~qh7jw!EX^GUh4jGIL@SIKYQpb*b7{i+V5*ygJq zbH4-Srk6M{nuF-I4vdb|Egc!&5@=i|yv0gYZsxZYkOy_fCRGq%fol$K23`fSb FYyd^tA}s&_ delta 106 zcmX>)f%WJFR-OQFW)=|!4j^nQ+{m+Aj;X0|^GUh4jGNOOA~`m1P}m?p{i+V5*ygJq zbH4-Srk6M{nuF-I4vdb|Z5&5@=niiWR#lz!hunRiCc3zpChB@^lk2pV%ujp IGOlF<0Bvz1c>n+a diff --git a/docs/components/odt/en-US/widgets/Line.odt b/docs/components/odt/en-US/widgets/Line.odt index 0356bbaf2a57df5386e14e4c6c7faeecfa43bf25..5a99c4420bfc7f655aa32013839a980e7a32c32d 100644 GIT binary patch delta 52 zcmbO@fpy{pR-OQFW)=|!4j{}c*~rr_$COvnJXLP{R5`|#ia_>s2M0!TAicfPfpG>q E0Ci;!*#H0l delta 52 zcmbO@fpy{pR-OQFW)=|!4j^nQ+{n`|$JA8VJXLP{R5`|#ia_>s2M0!TAicfPfpG>q E0DCwO9RL6T diff --git a/docs/components/odt/en-US/widgets/LineChart (Dashboard).odt b/docs/components/odt/en-US/widgets/LineChart (Dashboard).odt index 56cfaced19e37bc73d12d01297a6f025d5fe3423..346d5a5e491acee4fdb63233ca714eb738291b09 100644 GIT binary patch delta 56 zcmX?bpX0!N4xRvSW)=|!4j{}g*~qg&mMOoad7o_iK3T@?`(&A>aRT|%!_=9~f%Nu% IbtXd&0QejcCIA2c delta 56 zcmX?bpX0!N4xRvSW)=|!4j^nU+{m**mZ`b0d7o_iK3T@?`(&A>aRT|%!_=9~f%Nu% IbtXd&0RDFoY5)KL 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 910a3041c61147f300a7c06691a42743afb44e38..edf11c2fe6bb1a5013fb141c20b31640c4255c31 100644 GIT binary patch delta 56 zcmZ3mhjYOmPM!d7W)=|!4j{}g*~s%*nkm1enNg;lQHF6lqYTqtOCW#xflwxMAie!( ID3dw|0KAJ3CIA2c delta 56 zcmZ3mhjYOmPM!d7W)=|!4j^nU+{p7;nyI<4nNg;lQHF6lqYTqtOCW#xflwxMAie!( ID3dw|0K(=FY5)KL diff --git a/docs/components/odt/en-US/widgets/List (Dashboard).odt b/docs/components/odt/en-US/widgets/List (Dashboard).odt index 99531692b94201343824d03fa444dea9507e2b8e..19c0c2d6fe35e1179fe24d831598468262e15d15 100644 GIT binary patch delta 98 zcmex$hyB+bcAfxlW)=|!4j{}c*~qh0oGGtl^JejP>o%QVCBJ$0v3QQ@2QD#+Z9edB z?suTn^!R6t<{)~;Gsf=edCwW;n5G|_-uIkQbGqzvMinOaXVaaZGpcUi{+#hJ8vx(_ BDe(XR delta 99 zcmex$hyB+bcAfxlW)=|!4j^nQ+{m+3oT;gB^JejP>ox~Ii{#im``8Bg=?5+`ifumd zZti!W-1PWojOHME#xut5=|#^O<(Q@)n?C6|qv~|o=Zq>$-_A{Ue$J@5efx99!)yQ@ Cmn%I0 diff --git a/docs/components/odt/en-US/widgets/List (LVGL).odt b/docs/components/odt/en-US/widgets/List (LVGL).odt index ec9bf075178bdeb2e5b6152d07a38e35f3d66730..0acd18833c4f95b3fa7347cf25ada400638cc1bf 100644 GIT binary patch delta 52 zcmey-$NHm>l_$WPnMH(w0|@gv{^ E0Kl_$WPnMH(w0|=W6H}brbWojyH{v*5nk1XR#MId|na(hN|Aie#8J>v{^ E0LfYrv{^ E0K`lYr~m)} delta 52 zcmey_$NIC6l_$WPnMH(w0|=W6H}brfWojyH{wurvuPozAMId|n3VTL#Aie#eJ>v{^ E0LmW`>;M1& diff --git a/docs/components/odt/en-US/widgets/Markdown.odt b/docs/components/odt/en-US/widgets/Markdown.odt index 5894a05045d72dd32f4e8ae70239fbb4c1e79428..2b4438aea1e4f74212b0e732a1c10f436d0cb1c4 100644 GIT binary patch delta 52 zcmex=js5>McAfxlW)=|!4j{}g*~qg>gekwId56gM9U_dY&H>reQyw##1L^H^A2U8; F2LRqX6B+;j delta 52 zcmex=js5>McAfxlW)=|!4j^nU+{m*^gsHi(d56gM9U_dY&H>reQyw##1L^H^A2U8; F2LR*_6J7uS diff --git a/docs/components/odt/en-US/widgets/Menu.odt b/docs/components/odt/en-US/widgets/Menu.odt index cd2ed44aeaccb8c6771499986f0480a63f487f98..9d380a756b2c0fc684cf340a3b8c64f969bf5434 100644 GIT binary patch delta 94 zcmey-$NHm>l_$WPnMH(w0|@gl_$WPnMH(w0|=W6H}brbWojzi{73dJ<7N+yRq~r3%g1wU{^Y*-J5YG~ va(hN|5dFZO(Q$f?1EU<%efjA<4vd=9r5zYmnELIfJ326`Zr|#_c$f_UOHm;b diff --git a/docs/components/odt/en-US/widgets/MessageBox.odt b/docs/components/odt/en-US/widgets/MessageBox.odt index 634af4014129b5a114c7b103d41bc839d5c3ae06..814d0036b31035fcc7f2d1e870163d3fa7f17ef9 100644 GIT binary patch delta 104 zcmez0$NImIl_$WPnMH(w0|@g+$V(=++Wi5kk&WgHl_n5NlJ_i$iT1#8)U$$@b#8vr2z BBKH6Q diff --git a/docs/components/odt/en-US/widgets/Meter.odt b/docs/components/odt/en-US/widgets/Meter.odt index cff14120b6bd8f7d6297685e0634f20e8539d216..6900bc984bf342ee82de8d7968967553938ee741 100644 GIT binary patch delta 52 zcmX>#f%Vh`R-OQFW)=|!4j{}c*~oK1jw!FC`JCMLb8?I;6@l#Ol@5&NKzjQo2gVuf E0HHz#f%Vh`R-OQFW)=|!4j^nQ+{kl4j;X1z`JCMLb8?I;6@l#Ol@5&NKzjQo2gVuf E0H+lYtN;K2 diff --git a/docs/components/odt/en-US/widgets/MultilineText.odt b/docs/components/odt/en-US/widgets/MultilineText.odt index 5cbf7ab4a715e4b45a5453765d5f47698ad4a626..758bc2d9d2169a98c68018a6d2dcbb78d1e0b442 100644 GIT binary patch delta 103 zcmX?mgZ=CccAfxlW)=|!4j{}g*~n8N%9LNSxlQ!ly3Hz2A~`na9oZm1eewlHvFQt* zGO}!*{$}QPpn~Z}PZ-TXboLX*?&+>i8ReL=j!ZUtB0v4r6GknjlV_%jJ!RC~-u0C6 GFdG0hAu7KB delta 104 zcmX?mgZ=CccAfxlW)=|!4j^nU+{jZQ%G6xAxlQ!ly3Lo*tdifHcO;%;`s53YV$&Bq zWn|er{msnpKn2r{o-mq&=i~hbN3GOj1v#i#=sj-QM+- H@h}?zkwz;v diff --git a/docs/components/odt/en-US/widgets/NumberInput.odt b/docs/components/odt/en-US/widgets/NumberInput.odt index 509b5d2c02e62f40135d2213adb1111ec8d8ab06..46bf57f3b29183275e9a132746efb7f5dd4e58af 100644 GIT binary patch delta 52 zcmbPngMG#gcAfxlW)=|!4j{}c*~sH8%9K~q94NXyP?T}iIUsxb-^YyRKzh5`6UImE E0GzfFO#lD@ delta 52 zcmbPngMG#gcAfxlW)=|!4j^nU+{oiB%G6xg94NXyP?T}iIUsxb-^YyRKzh5`6UImE E0HWX#l>h($ diff --git a/docs/components/odt/en-US/widgets/Panel.odt b/docs/components/odt/en-US/widgets/Panel.odt index d21040fa92aa3d3a9bddc70dae9a2ab10bd7aaf8..add9dfe1b2de706060cb75c120f6d1bd333a36f2 100644 GIT binary patch delta 52 zcmdnp&$_#xl_$WPnMH(w0|@greBcCvu1L^IPo-jUQ F2LRUP64n3! delta 52 zcmexzgZ;}5cAfxlW)=|!4j^nU+{iOul&QI}d9CR7wW5rx&H>reBcCvu1L^IPo-jUQ F2LRl-6B+;j 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 b735714c177ffafd0f1808ee197742e0f713a06e..5396159732720db6c319a982447d60193a790518 100644 GIT binary patch delta 96 zcmdn|h<)=TcAfxlW)=|!4j{}g*~pV4%9LNSxk@yGZF7_Lr!||;NNJIk^Zr!x#Y$4k{66Z zK$+HCL`x8bU zpv-j9CyeGG+V2UYnb$%W#|+kpZi>;NSa BBr5;_ 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 476aa9a976a55b3ae552a43fb265c8dc1e4658c2..b8089ed69ca75361b1ed22b677c68f627cbfe37d 100644 GIT binary patch delta 52 zcmdmSoqfl3cAfxlW)=|!4j{}g*~s%)gekwI`J>48k0Ok#&H>re=RRgM2h!WGJ!X8w F4glBt6RQ9K delta 52 zcmdmSoqfl3cAfxlW)=|!4j^nU+{p7-gsHi(`J>48k0Ok#&H>re=RRgM2h!WGJ!X8w F4glTG6Yl^3 diff --git a/docs/components/odt/en-US/widgets/Radio.odt b/docs/components/odt/en-US/widgets/Radio.odt index c548abbe03db2cfeb453e3bb41944ef71a19ed30..2a9e7491f7cb66a4231164fb02d3ae8566fc757e 100644 GIT binary patch delta 103 zcmX?mll|;XcAfxlW)=|!4j{}g*~s%llqtVtGn?4Eb(@zwiR9S)?#KrD>B1Ko#ilDf zV`SMZ{&wbfpn~a}o-mq&=+{peyQd$0$|%S5>d546Pvoa(J!RBl@;p0z+EYf&?Oe|o H53>OPYWpk5 delta 104 zcmX?mll|;XcAfxlW)=|!4j^nU+{p7ol&QIJGn?4Eb(@3Fu9DyU?npexbm5DPV$&6# zF|uqHe>?L#P{H&~PZ-TX^y?>#-O~>~Wt3xjb!7U(r;M7@3!XBnFwJ^0ecDq-)$Lr* I7!R`n0FGfSKL7v# diff --git a/docs/components/odt/en-US/widgets/Rectangle (Dashboard).odt b/docs/components/odt/en-US/widgets/Rectangle (Dashboard).odt index a06947c46311254c93b75433ff03a5b1f5b47713..9e8b621e284702f9f2e3b9c151998351607191ee 100644 GIT binary patch delta 103 zcmbPnoqfi2cAfxlW)=|!4j{}c*~oKPgek9N^F@(&>o(^G#evifz94 zdhU0i-1OSVjOHME+hfM==@XtX$}w#{Jh}0){Pgor7}=&OPs>v+Z delta 103 zcmbPnoqfi2cAfxlW)=|!4j^nU+{klSgsHi3^F@(&>o&`sStY-D=izvc>G#evifz94 zdhU0i-1OSVjOHME+hfM=={-*v<(Re}o@{VNdHVS$jBL}bpD?O0r9PgX_=Hh)`_(6m GhuHv}UM#Z! 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 dfe28fc4f0947e9af2cd0813c792626440b2d7fa..325475e35274d607de713de837363d9d892b3e6a 100644 GIT binary patch delta 52 zcmX?cmHot3cAfxlW)=|!4j{}g*~s%*m?^)cnNegrqX^@wb3pd=wT~Fhf%Nugj~E}Z F0|2yF5)=Rc delta 52 zcmX?cmHot3cAfxlW)=|!4j^nU+{p7;n5nt2nNegrqX^@wb3pd=wT~Fhf%Nugj~E}Z F0|2@z5?BBL 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 419db01c429eaa865f8092a2a0612c90b97375b7..d112d7a9833ba2a1637269297a4ad7ea7ba27417 100644 GIT binary patch delta 99 zcmeCY&E9#NohQJXnMH(w0|@g=Hu7u{W6Cetd`Rrwy3GksBRMv&I=VrA`uU5DVw=yu zo%$&Mc&lokgAA81lm<<5S C4=L;b delta 103 zcmeCY&E9#NohQJXnMH(w0|=W7H}Y%|V`?tkd`Rrwy3PFOR>^N(bu^x1`uU5DVw=yu zo%?_Rx diff --git a/docs/components/odt/en-US/widgets/Roller (LVGL).odt b/docs/components/odt/en-US/widgets/Roller (LVGL).odt index 988afe7747cd36249f6080f43e22bbe17a397046..4563204eae26feca5ff2f780978dea00da0ab762 100644 GIT binary patch delta 52 zcmbO_iFN8ER-OQFW)=|!4j{}c*~rr^&y-ivJX3!AOnJtYia_>s7e_{OAicfTk#Pn) E0C}1Y{r~^~ delta 52 zcmbO_iFN8ER-OQFW)=|!4j^nU+{n`{&(vJlJX3!AOnJtYia_>s7e_{OAicfTk#Pn) E0Dr^}MgRZ+ diff --git a/docs/components/odt/en-US/widgets/Scale.odt b/docs/components/odt/en-US/widgets/Scale.odt index 9a837b269d9b611c3a1a679d1f086dd6f2c7cbdd..8206f571d70fadd97ab4841edfab0bbe10157183 100644 GIT binary patch delta 52 zcmdlnfpy0OR-OQFW)=|!4j{}c*~qg_jw!FCd5_%oJ#vgI6@l#O=?;wMKzjQE2gVuf E0F!7B>Hq)$ delta 52 zcmdlnfpy0OR-OQFW)=|!4j^nU+{m*|j;Xn@d5_%oJ#vgI6@l#O=?;wMKzjQE2gVuf E0GW~yG5`Po diff --git a/docs/components/odt/en-US/widgets/ScrollBar.odt b/docs/components/odt/en-US/widgets/ScrollBar.odt index 63173241adce5ae922558dae3f866ecd217e0a03..a6e7ecbc882ca05b12afceffc2390e1163245961 100644 GIT binary patch delta 116 zcmcb5jPvR-PM!d7W)=|!4j{}g*~lX-!IWRptSGTvQG&6;Y5Ij2Cb8*!$&3=)XGSrW za%{IrX3YN%R55*R6q7lS-u^6#DUosdu_U0f6){YF%u}Nnrwb-C3Qu>AVbWkcJUu6d R$!7ZNI3~XBUt*XN*#I9IB*Xv! delta 122 zcmcb5jPvR-PM!d7W)=|!4j^nU+{hy=!PH#XtSGTvQG&6;Y5Vag#!`;y>!TPYreBC* zlG^T&%$WThsABrsC?<0tz5Q7fQzGN^))*!g=BZJP(;q}J%1u8N!z433Hin6h=}Xe| Z+!!W_>FzO1V$)y8G4XBx62p|p1^{X8C|v*m diff --git a/docs/components/odt/en-US/widgets/Select.odt b/docs/components/odt/en-US/widgets/Select.odt index 5b0eddcee002973993f898c2e40463a9dfe94ebd..9faa6bddc5808cdb9465119e55f2b27e201e092f 100644 GIT binary patch delta 52 zcmX?lgZ=0YcAfxlW)=|!4j{}c*~n8M%9K~qTqnA{PLy%gIUsww))Pi^AiX{L3F9Mn E0J38di2wiq delta 52 zcmX?lgZ=0YcAfxlW)=|!4j^nQ+{jZP%G6ZYTqnA{PLy%gIUsww))Pi^AiX{L3F9Mn E0Jt_0%>V!Z diff --git a/docs/components/odt/en-US/widgets/Slider (Dashboard).odt b/docs/components/odt/en-US/widgets/Slider (Dashboard).odt index 0d769e5a2076502c8e78f6ade2bbc5aba4c58975..67cc5e6f2c72f8cc6ed300531aab54fb312930b0 100644 GIT binary patch delta 52 zcmX?hll|CDcAfxlW)=|!4j{}g*~s%zlqtWY`M>D)|Duem&H>reS3hAi2h!W0JYjsq F4gllg6czvg delta 52 zcmX?hll|CDcAfxlW)=|!4j^nU+{p7$l&QI}`M>D)|Duem&H>reS3hAi2h!W0JYjsq F4gl%36j}fP 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 d2a54e6aed22a66bb5e42307a524130fa76b6f93..5b7eb67064302fae3b34dc82dcdb04bdb7b97316 100644 GIT binary patch delta 98 zcmbPpoqf)AcAfxlW)=|!4j{}g*~oKTgekvd^Hq^|>oylZj^x<9_wWY!>5tAcifw-M zdhU0i-1NrBjOHME*JH-+=~JFC$}#OcJh}C;{B+AFj9N?*XQrnozN$StY-D@8Nik>5tAcifw-M zdhU0i-1NrBjOHME*JH-+=@XtX$}#OcJbl9xM$PH=PZ(90G9OP*eZr`^{pJ(K!)yTg Cw<|>e diff --git a/docs/components/odt/en-US/widgets/Slider (LVGL).odt b/docs/components/odt/en-US/widgets/Slider (LVGL).odt index d7a7c74d849cc886e54607e2f69c27755e545899..4e834f41568cb5a0979783e46a85176b5cd18256 100644 GIT binary patch delta 106 zcmZ27g>}gkR-OQFW)=|!4j{}c*~l|Xfhn(K^9qHxjGMn`t&-o|uN2QQeTyEW*yb%> zbH4-SrUyGQnuF*bCq~EV63&cr(_cF=@=kXKv5q@2sxVnQO@Hges5*VBC!^T*a%aZ1 FYyeY)BLDyZ delta 106 zcmZ27g>}gkR-OQFW)=|!4j^nU+{iOafvLH0^9qHxjGJAZA~`nqD{YXUzD18wZ1Wbc zx!-|u(}SHD%|UdJ6QkpF8D~bh>93s_d8fNOGfGWA?!>6V^h#^`TPH@%=~F!!#kQ9_ IGp=O=07POVPyhe` diff --git a/docs/components/odt/en-US/widgets/Span.odt b/docs/components/odt/en-US/widgets/Span.odt index 5587ddf4d3b2969a4f8c7b6dd8c797fed99148aa..85130abb7d322ac419a72e0b214694458367511a 100644 GIT binary patch delta 52 zcmey?$NH_0l_$WPnMH(w0|@goAie#bJ>v{^ E0KxqclK=n! delta 52 zcmey?$NH_0l_$WPnMH(w0|=W7H}brZWoj;L{w2Hpmn`E-MId|nQhP>oAie#bJ>v{^ E0LUj1+W-In diff --git a/docs/components/odt/en-US/widgets/Spinbox.odt b/docs/components/odt/en-US/widgets/Spinbox.odt index 43ad0b76d732e89d3fca2ed8d263a09564432f57..fb4edd7659d27a01a45fe0ce5c58a8443bcca67c 100644 GIT binary patch delta 106 zcmX>+h4t_hR-OQFW)=|!4j{}c*~qg~fhn(K^Kpf@jGKkESIKW)rxedI{jwgT*yhV# zbH4-SrWZLenuF-oPK=Jz&7B$LrgJ$n@=i|zv7R|GsxU=4P3LiDRGq%XlTmE@G-t-O FYyd}8A~65} delta 106 zcmX>+h4t_hR-OQFW)=|!4j^nU+{m+2fvLH0^Kpf@jGI%OA~`m%Q`#Uu{jwgT*yhV# zbH4-SrWZLenuF-oPK=Jzt(_U=rgJ$n@=i~4W|W%#%!yHjiBo$zk29m@^evu@V%w)V IGp=O=0B`ytfdBvi diff --git a/docs/components/odt/en-US/widgets/Spinner (Dashboard).odt b/docs/components/odt/en-US/widgets/Spinner (Dashboard).odt index 36d026f383bad35212645bb755d227ab5495135d..22e0852213c1c16bf48fd4e0a936fd77e4f27404 100644 GIT binary patch delta 100 zcmex#js4R#cAfxlW)=|!4j{}g*~l|jgekvd^Jo)&5y-I%b6T9zc_)jWk(kc^gi(vh{_%9{Cyc7oAHQN0+kW&3<61TV DCblX` delta 100 zcmex#js4R#cAfxlW)=|!4j^nU+{iOmgsHi3^Jo$8nj^x-p`S1q$&5K@d{tgtL z9{!lo97Ioe%-B6W>j|UWbjv4_gdklud8o^b{{ E0ImBF-2eap delta 52 zcmcc9$9kual_$WPnMH(w0|=W7H}YJPWoj;LejvO3fh^-nMId{6w>_gdklud8o^b{{ E0JJ3$B>(^b diff --git a/docs/components/odt/en-US/widgets/Switch (Dashboard).odt b/docs/components/odt/en-US/widgets/Switch (Dashboard).odt index ede26b65f4fa6fb20d12c53b041a35055d710464..ac51aa833b5b25d06cf7e27341379760122685f7 100644 GIT binary patch delta 52 zcmaESo&E83cAfxlW)=|!4j{}g*~r5u%9LNyEF-#IMwD^YIUsxbiN}oQKzcjl6UImE E0H$FO+yDRo delta 52 zcmaESo&E83cAfxlW)=|!4j^nU+{nWx%G6xgEF-#IMwD^YIUsxbiN}oQKzcjl6UImE E0IW0-AOHXW 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 c35a4da917884dd311fe4b94a7e85ae6a4041e9e..271fac9e8060caa982cd02121ad5335178713fed 100644 GIT binary patch delta 52 zcmdmTjeW~CcAfxlW)=|!4j{}g*~k+w!jxaqoGY?DSA=oZIUsww$NH;}l_$WPnMH(w0|@g$NH;}l_$WPnMH(w0|=W7H}ZUtWoja7-z5p E0C&s|B>(^b delta 52 zcmccI&w9C^l_$WPnMH(w0|=W7H}ZJOF*O%9hs$jbmt$P12xL!Za$qzE(%Y>a7-z5p E0DbljZ2$lO diff --git a/docs/components/odt/en-US/widgets/Table.odt b/docs/components/odt/en-US/widgets/Table.odt index 0b82121538c8452ed88cb48dd71bba0b55f0bc3c..f623fc6adb0cf2eb8ae7176e2bddc26635340873 100644 GIT binary patch delta 52 zcmey;$NHs@l_$WPnMH(w0|@gv{^ E0Kjt*g#Z8m delta 52 zcmey;$NHs@l_$WPnMH(w0|=W7H}braWoj;L{vo^lhb-etMId|nVtYn&Aie#LJ>v{^ E0LGmW%>V!Z diff --git a/docs/components/odt/en-US/widgets/Tabulator.odt b/docs/components/odt/en-US/widgets/Tabulator.odt index 61b4a58ec8c45d6d4322d05cd64de8010f57894e..3234bb40653ef6f87b6c825a75423a4c0e5a5899 100644 GIT binary patch delta 52 zcmaEJll{$2cAfxlW)=|!4j{}g*~lX<#*|;utSYu$Rg7`fIUsxb#V3sBKzcjZQ^rT^ E0IqKlBme*a delta 52 zcmaEJll{$2cAfxlW)=|!4j^nU+{hy?#?)NctSYu$Rg7`fIUsxb#V3sBKzcjZQ^rT^ E0JK68XaE2J diff --git a/docs/components/odt/en-US/widgets/Tabview.odt b/docs/components/odt/en-US/widgets/Tabview.odt index f2997b5d2010abb0050370ada95c2746d08dd880..506599c20bbf5a6a751e088481f444f6abf2be1d 100644 GIT binary patch delta 105 zcmeC#!`icll_$WPnMH(w0|@gljF4%r>_iSo)s8iR9Qk^T-DI>H97)if!Ka zX6|>O-1OKdjOHME+7rg^=><<2<(Q@(nVk4Ue){^SjBL}TpE9a2eK|AT@hPL`_N`AD H53>OPw2LgL delta 103 zcmexygZ;-1cAfxlW)=|!4j^nU+{m+7l&QIJ^G4Bk>o)&8vr2yR%p>s})AwCq6x+P- z&D`%mx#_V_7|lWSv?q++({r9O$}vqnGFjlP^7Qpj8QG>wKV?*5a(y!0@hPL~_N`AD H53>OP-{vfY diff --git a/docs/components/odt/en-US/widgets/Textarea.odt b/docs/components/odt/en-US/widgets/Textarea.odt index 22272631f5f065555b5f7e19835bce12bfb940c0..3beea8106452b9db1ab3779c5b135991c263260a 100644 GIT binary patch delta 52 zcmZpl!rDHCl_$WPnMH(w0|@g(2}$T6-|1hS{Ew`Vj5(%WCyGtOWK E0BFAs-2eap delta 52 zcmZqZXKm(2}$T6-|1hS{Ew`Vj5(%WCyGtOWK E0B-3IB>(^b diff --git a/docs/components/odt/en-US/widgets/ToggleButton.odt b/docs/components/odt/en-US/widgets/ToggleButton.odt index 65935c73623f5a809a1940a171b11eff96454760..e252b17cd87dacb803b7c1f950c87242c9329461 100644 GIT binary patch delta 52 zcmdmToqfx7cAfxlW)=|!4j{}g*~oKWgekwI`K`$Iw<3(I&H>reXFg^$2h!UwJ!X8w F4gl2W6ORA@ delta 52 zcmdmToqfx7cAfxlW)=|!4j^nU+{klZgsHi(`K`$Iw<3(I&H>reXFg^$2h!UwJ!X8w F4glJ^6Vm_y diff --git a/docs/components/odt/en-US/widgets/UpDown.odt b/docs/components/odt/en-US/widgets/UpDown.odt index 3ffc0c8b6754d90f123d0d8c8cf0d9a4283e0727..95f73447361a5ea9ff8bc62147430165361e7e52 100644 GIT binary patch delta 52 zcmZ2*gMGmbcAfxlW)=|!4j{}g*~sH9%9LNy94WdzQj~GkIUsvF>k~$EAidr03F9Mn E0G2@ziU0rr delta 52 zcmZ2*gMGmbcAfxlW)=|!4j^nU+{oiC%G6xg94WdzQj~GkIUsvF>k~$EAidr03F9Mn E0Gt#M&Hw-a diff --git a/docs/components/odt/en-US/widgets/Window.odt b/docs/components/odt/en-US/widgets/Window.odt index 7acc4681a471888fe24eae201fd7b3c1d2c57153..aa9dbd0d6c947dbb6e3439ff39bcf35aaddd3c81 100644 GIT binary patch delta 52 zcmey-$NHm>l_$WPnMH(w0|@gv{^ E0Kl_$WPnMH(w0|=W7H}brbWoj;L{v*5nk1XR#MId|na(hN|Aie#8J>v{^ E0Lift=>Px# 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"; +*/