diff --git a/.idea/ant.xml b/.idea/ant.xml
new file mode 100644
index 000000000..a2a476982
--- /dev/null
+++ b/.idea/ant.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 000000000..919ce1f1f
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 58d13c02c..85b274f26 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -9,23 +9,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 7e340a776..9a55c2de1 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/libraries/ant_antlr.xml b/.idea/libraries/ant_antlr.xml
new file mode 100644
index 000000000..59652667b
--- /dev/null
+++ b/.idea/libraries/ant_antlr.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/ant_launcher.xml b/.idea/libraries/ant_launcher.xml
new file mode 100644
index 000000000..ef0794b5f
--- /dev/null
+++ b/.idea/libraries/ant_launcher.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/apache_ant_junit.xml b/.idea/libraries/apache_ant_junit.xml
new file mode 100644
index 000000000..9b11bfcbb
--- /dev/null
+++ b/.idea/libraries/apache_ant_junit.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4981e477a..59b4d604e 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -10,6 +10,7 @@
+
diff --git a/.mps/encodings.xml b/.mps/encodings.xml
deleted file mode 100644
index 15a15b218..000000000
--- a/.mps/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.mps/modules.xml b/.mps/modules.xml
index 995e49edc..a08ecb86d 100644
--- a/.mps/modules.xml
+++ b/.mps/modules.xml
@@ -31,6 +31,7 @@
+
\ No newline at end of file
diff --git a/.mps/runConfigurations/MPS_with_IEC_61499.xml b/.mps/runConfigurations/MPS_with_IEC_61499.xml
index 20ed40dd2..d787223d3 100644
--- a/.mps/runConfigurations/MPS_with_IEC_61499.xml
+++ b/.mps/runConfigurations/MPS_with_IEC_61499.xml
@@ -4,15 +4,13 @@
-
+
diff --git a/code/4diac-integration/solutions/org.fbme.ide.integration.fordiac/models/org.fbme.ide.integration.fordiac.mps b/code/4diac-integration/solutions/org.fbme.ide.integration.fordiac/models/org.fbme.ide.integration.fordiac.mps
index aa5d31040..85d87ef57 100644
--- a/code/4diac-integration/solutions/org.fbme.ide.integration.fordiac/models/org.fbme.ide.integration.fordiac.mps
+++ b/code/4diac-integration/solutions/org.fbme.ide.integration.fordiac/models/org.fbme.ide.integration.fordiac.mps
@@ -474,6 +474,7 @@
+
@@ -487,6 +488,7 @@
+
@@ -3052,6 +3054,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_DESERIALIZER.fbt b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_DESERIALIZER.fbt
new file mode 100644
index 000000000..9d8cc093e
--- /dev/null
+++ b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_DESERIALIZER.fbt
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_FORMER.fbt b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_FORMER.fbt
new file mode 100644
index 000000000..c4d253659
--- /dev/null
+++ b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_FORMER.fbt
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_PARSER.fbt b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_PARSER.fbt
new file mode 100644
index 000000000..0ec15d196
--- /dev/null
+++ b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_PARSER.fbt
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_SERIALIZER.fbt b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_SERIALIZER.fbt
new file mode 100644
index 000000000..280f68cd2
--- /dev/null
+++ b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/JSON_SERIALIZER.fbt
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/TYPE_DETECTOR.fbt b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/TYPE_DETECTOR.fbt
new file mode 100644
index 000000000..ea9ffb7af
--- /dev/null
+++ b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/TYPE_DETECTOR.fbt
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/TYPE_SERIALIZER.fbt b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/TYPE_SERIALIZER.fbt
new file mode 100644
index 000000000..bdc97c05d
--- /dev/null
+++ b/code/4diac-integration/solutions/stdlib/models/iec61499.4diac.stdlib/hmi-blocks/TYPE_SERIALIZER.fbt
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/cat_visual/README.md b/code/cat_visual/README.md
new file mode 100644
index 000000000..a2cb49d34
--- /dev/null
+++ b/code/cat_visual/README.md
@@ -0,0 +1,14 @@
+# compose_template
+
+Виды примитивных блоков для поддержки
+* checkbox
+* radio
+* text choice
+* different toggles
+
+Interfaces:
+* Zoomable
+* Positioned
+* ZIndexed
+* Grouped
+*
\ No newline at end of file
diff --git a/code/cat_visual/build.gradle.kts b/code/cat_visual/build.gradle.kts
new file mode 100644
index 000000000..c92353dac
--- /dev/null
+++ b/code/cat_visual/build.gradle.kts
@@ -0,0 +1,40 @@
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+ kotlin("jvm") version "1.8.0"
+ id("org.jetbrains.compose") version "1.3.1"
+ kotlin("plugin.serialization") version "1.8.0"
+}
+
+group = "fbme"
+version = "1.0"
+
+repositories {
+ google()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+}
+
+dependencies {
+ implementation(compose.desktop.currentOs)
+ implementation("com.hierynomus:asn-one:0.5.0")
+ implementation(kotlin("stdlib-jdk8"))
+ implementation("io.github.pdvrieze.xmlutil:serialization-jvm:0.84.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
+}
+
+tasks.withType {
+ kotlinOptions.jvmTarget = "11"
+}
+
+compose.desktop {
+ application {
+ mainClass = "MainKt"
+ nativeDistributions {
+ targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
+ packageName = "compose"
+ packageVersion = "1.0.0"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/cat_visual/gradle.properties b/code/cat_visual/gradle.properties
new file mode 100644
index 000000000..7fc6f1ff2
--- /dev/null
+++ b/code/cat_visual/gradle.properties
@@ -0,0 +1 @@
+kotlin.code.style=official
diff --git a/code/cat_visual/gradle/wrapper/gradle-wrapper.jar b/code/cat_visual/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..7f93135c4
Binary files /dev/null and b/code/cat_visual/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/code/cat_visual/gradle/wrapper/gradle-wrapper.properties b/code/cat_visual/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..3fa8f862f
--- /dev/null
+++ b/code/cat_visual/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/code/cat_visual/gradlew b/code/cat_visual/gradlew
new file mode 100755
index 000000000..744e882ed
--- /dev/null
+++ b/code/cat_visual/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MSYS* | MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/code/cat_visual/gradlew.bat b/code/cat_visual/gradlew.bat
new file mode 100644
index 000000000..ac1b06f93
--- /dev/null
+++ b/code/cat_visual/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/code/cat_visual/settings.gradle.kts b/code/cat_visual/settings.gradle.kts
new file mode 100644
index 000000000..bbba57708
--- /dev/null
+++ b/code/cat_visual/settings.gradle.kts
@@ -0,0 +1,10 @@
+pluginManagement {
+ repositories {
+ google()
+ gradlePluginPortal()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+ }
+
+}
+rootProject.name = "compose"
+
diff --git a/code/cat_visual/src/main/kotlin/Main.kt b/code/cat_visual/src/main/kotlin/Main.kt
new file mode 100644
index 000000000..879c16e8e
--- /dev/null
+++ b/code/cat_visual/src/main/kotlin/Main.kt
@@ -0,0 +1,192 @@
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.rememberTransformableState
+import androidx.compose.foundation.gestures.transformable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material.Button
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Scaffold
+import androidx.compose.material.Text
+import androidx.compose.runtime.*
+import androidx.compose.runtime.snapshots.SnapshotStateList
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.Window
+import androidx.compose.ui.window.application
+import androidx.compose.ui.window.rememberWindowState
+import androidx.compose.ui.zIndex
+import canvas.items.impl.CustomItem
+import canvas.items.impl.LampItem
+import canvas.items.impl.TextItem
+import canvas.items.impl.ToggleItem
+import canvas.items.interfaces.CanvasItemInterface
+import canvas.items.model.JsonCanvasModel
+import canvas.items.model.toItem
+import connection.*
+import example.COUNTER.CounterLampHMI
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import serializer.SerializationUtils
+import serializer.getConf
+import serializer.getMapping
+import serializer.getPlainMapping
+import java.io.File
+
+@Composable
+fun CanvasContext(listFigures: SnapshotStateList) {
+ Scaffold { innerPadding ->
+ Box(Modifier.fillMaxHeight().fillMaxWidth().background(Color.Gray)) {
+ listFigures.forEach { f -> f.create() }
+ }
+ }
+}
+
+fun buildMappingClient(modelFile: String, configFile: String = "", mode: String = ""): AbstractClient {
+ if (mode.equals("plain")) {
+ val modelText = File(modelFile).readText()
+ val mapping = getPlainMapping(modelText)
+
+ return PlainClient(mapping)
+ }
+
+ val modelText = File(modelFile).readText()
+ val mapping = getMapping(modelText)
+ val configText = File(configFile).readText()
+ val conf = getConf(configText)
+
+ if (mode.equals("json")) {
+ return JSONClient(mapping, conf)
+ }
+ return NamedClient(mapping, conf)
+}
+
+//val client = buildMappingClient("src/main/kotlin/example/COUNTER/COUNTER.xml", "src/main/kotlin/example/COUNTER/COUNTER_CONF.xml", "")
+val client = buildMappingClient("src/main/kotlin/example/COUNTER/COUNTER.xml", "src/main/kotlin/example/COUNTER/COMMON_CONF.xml", "json")
+//val client = buildMappingClient("src/main/kotlin/example/WATER_TANK/WATER_TANK.xml", "src/main/kotlin/example/WATER_TANK/WATER_TANK_CONF.xml", "")
+//val client = buildMappingClient("src/main/kotlin/example/WATER_TANK/WATER_TANK.xml", "src/main/kotlin/example/WATER_TANK/COMMON_CONF.xml", "json")
+
+@Composable
+fun canvas(
+ itemList: List,
+ deleteItem: (String) -> Unit,
+) {
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxHeight()
+ .fillMaxWidth()
+ .zIndex(0f),
+ ) {
+ items(itemList.size) { index ->
+ itemList[index].getContent { deleteItem(it)}
+ }
+ }
+}
+
+@Composable
+fun itemBar(
+ itemList: List,
+ addNewItem: (CanvasItemInterface) -> Unit
+) {
+ Column(
+ modifier = Modifier
+ .background(Color.LightGray)
+ .width(140.dp)
+ .fillMaxHeight()
+ .zIndex(-2f),
+ horizontalAlignment = Alignment.End,
+ ) {
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ addNewItem(TextItem(content = "AddedText"))
+ }
+ ) {
+ Text(text = "Text")
+ }
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ addNewItem(LampItem(client = client))
+ }
+ ) {
+ Text(text = "Lamp")
+ }
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ addNewItem(ToggleItem(client = client))
+ }
+ ) {
+ Text(text = "Toggle")
+ }
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ addNewItem(LampItem(client = client))
+ }
+ ) {
+ Text(text = "Box")
+ }
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ addNewItem(LampItem(client = client))
+ }
+ ) {
+ Text(text = "CheckBox")
+ }
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ addNewItem(LampItem(client = client))
+ }
+ ) {
+ Text(text = "RadioButton")
+ }
+
+ Button(
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).width(130.dp),
+ onClick = {
+ val x = itemList.map {it.toModel()}
+ val json = Json.encodeToString(x)
+ SerializationUtils.saveSnapshot(json)
+ }
+ ) {
+ Text(text = "save")
+ }
+ }
+}
+
+fun main() = application {
+ Window(
+ onCloseRequest = ::exitApplication,
+ title = "Canvas for CAT",
+ state = rememberWindowState(width = 600.dp, height = 600.dp)
+ ) {
+ val listxxx = Json.decodeFromString>(SerializationUtils.readSnapshot())
+ var itemList by remember { mutableStateOf(listxxx.map { it.toItem(client) }) }
+ MaterialTheme {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .fillMaxHeight(),
+ ) {
+ itemBar(itemList) { item ->
+ itemList += listOf(item)
+ }
+ canvas(itemList) { idToDelete ->
+ itemList = itemList.filter { it.id.toString() != idToDelete }
+ val x = 1
+ println(itemList.map { it.id })
+ }
+ client.retrieveValues()
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/cat_visual/src/main/kotlin/canvas/Canvas.kt b/code/cat_visual/src/main/kotlin/canvas/Canvas.kt
new file mode 100644
index 000000000..1688219d8
--- /dev/null
+++ b/code/cat_visual/src/main/kotlin/canvas/Canvas.kt
@@ -0,0 +1,16 @@
+import androidx.compose.desktop.ui.tooling.preview.Preview
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.Button
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.*
+import androidx.compose.ui.Modifier
+
+@Composable
+fun CustomCanvas() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ }
+}
+
diff --git a/code/cat_visual/src/main/kotlin/canvas/UpperPlate.kt b/code/cat_visual/src/main/kotlin/canvas/UpperPlate.kt
new file mode 100644
index 000000000..12a011b5c
--- /dev/null
+++ b/code/cat_visual/src/main/kotlin/canvas/UpperPlate.kt
@@ -0,0 +1,91 @@
+import androidx.compose.desktop.ui.tooling.preview.Preview
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.Button
+import androidx.compose.material.Checkbox
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.*
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun UpperPlate() {
+ Row(horizontalArrangement = Arrangement.spacedBy(5.dp)) {
+ PointerButton()
+ }
+}
+@Composable
+@Preview
+fun PointerButton() {
+ var text by remember { mutableStateOf("P") }
+
+ MaterialTheme {
+ Button(onClick = {
+ text = "O"
+ }) {
+ Text(text)
+ }
+ }
+}
+
+@Composable
+@Preview
+fun RectangleButton(onClickFun: () -> Unit) {
+ var text by remember { mutableStateOf("R") }
+
+ MaterialTheme {
+ Button(onClick = onClickFun) {
+ Text(text)
+ }
+ }
+}
+
+
+@Composable
+@Preview
+fun CheckboxButton(onClickFun: () -> Unit) {
+ var text by remember { mutableStateOf("CB") }
+
+ MaterialTheme {
+ Button(onClick = onClickFun) {
+ Text(text)
+ }
+ }
+}
+
+@Composable
+@Preview
+fun RadioButton(onClickFun: () -> Unit) {
+ var text by remember { mutableStateOf("RB") }
+
+ MaterialTheme {
+ Button(onClick = onClickFun) {
+ Text(text)
+ }
+ }
+}
+
+@Composable
+@Preview
+fun ToggleButton(onClickFun: () -> Unit) {
+ var text by remember { mutableStateOf("TB") }
+
+ MaterialTheme {
+ Button(onClick = onClickFun) {
+ Text(text)
+ }
+ }
+}
+
+@Composable
+@Preview
+fun DropdownButton(onClickFun: () -> Unit) {
+ var text by remember { mutableStateOf("DB") }
+
+ MaterialTheme {
+ Button(onClick = onClickFun) {
+ Text(text)
+ }
+ }
+}
diff --git a/code/cat_visual/src/main/kotlin/canvas/exceptions/Exceptions.kt b/code/cat_visual/src/main/kotlin/canvas/exceptions/Exceptions.kt
new file mode 100644
index 000000000..f76d22dd4
--- /dev/null
+++ b/code/cat_visual/src/main/kotlin/canvas/exceptions/Exceptions.kt
@@ -0,0 +1,4 @@
+package canvas.exceptions
+
+class UnknownTypeItemException(id: String, unresolvedType: String):
+ RuntimeException("Can't resolve type: $unresolvedType, for id: $id")
\ No newline at end of file
diff --git a/code/cat_visual/src/main/kotlin/canvas/items/Draggable.kt b/code/cat_visual/src/main/kotlin/canvas/items/Draggable.kt
new file mode 100644
index 000000000..51125994a
--- /dev/null
+++ b/code/cat_visual/src/main/kotlin/canvas/items/Draggable.kt
@@ -0,0 +1,34 @@
+package canvas.items
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.detectDragGestures
+import androidx.compose.foundation.layout.offset
+import androidx.compose.runtime.MutableState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.changedToUp
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.dp
+
+interface Draggable {
+ fun Modifier.makeDraggable(
+ density: Density,
+ x: MutableState,
+ y: MutableState,
+ ): Modifier =
+ this.offset(
+ (x.value / density.density).dp,
+ (y.value / density.density).dp
+ ).pointerInput(Unit) {
+ detectDragGestures { change, dragAmount ->
+ change.consume()
+ x.value += dragAmount.x
+ y.value += dragAmount.y
+ }
+
+ }.clickable {
+ this.background(Color.LightGray)
+ }
+}
\ No newline at end of file
diff --git a/code/cat_visual/src/main/kotlin/canvas/items/impl/AbstractItem.kt b/code/cat_visual/src/main/kotlin/canvas/items/impl/AbstractItem.kt
new file mode 100644
index 000000000..6ef6d3271
--- /dev/null
+++ b/code/cat_visual/src/main/kotlin/canvas/items/impl/AbstractItem.kt
@@ -0,0 +1,47 @@
+package canvas.items.impl
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import canvas.items.interfaces.CanvasItemInterface
+import canvas.items.model.Input
+import canvas.items.model.JsonCanvasModel
+import canvas.items.model.Output
+import connection.AbstractClient
+import kotlinx.serialization.Serializable
+import serializer.SerializationUtils
+import java.util.UUID
+
+open class AbstractItem(
+ override val id: UUID = UUID.randomUUID(),
+ override var x: Float,
+ override var y: Float,
+ override val inputs: List = listOf(),
+ override val outputs: List
+
+
+
+
+
diff --git a/code/language/languages/org.fbme.ide.iec61499.lang/generator/template/org.fbme.ide.iec61499.lang.generator.main@generator.mps b/code/language/languages/org.fbme.ide.iec61499.lang/generator/template/org.fbme.ide.iec61499.lang.generator.main@generator.mps
index 0d483cb3c..3cd1cdb50 100644
--- a/code/language/languages/org.fbme.ide.iec61499.lang/generator/template/org.fbme.ide.iec61499.lang.generator.main@generator.mps
+++ b/code/language/languages/org.fbme.ide.iec61499.lang/generator/template/org.fbme.ide.iec61499.lang.generator.main@generator.mps
@@ -3,6 +3,7 @@
+
diff --git a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.actions.mps b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.actions.mps
index 957e003e7..299199ef6 100644
--- a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.actions.mps
+++ b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.actions.mps
@@ -114,5 +114,8 @@
+
+
+
diff --git a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.editor.mps b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.editor.mps
index e652db39a..543b3e73c 100644
--- a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.editor.mps
+++ b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.editor.mps
@@ -170,6 +170,7 @@
+
@@ -845,15 +846,8 @@
-
+
-
-
-
-
-
-
-
@@ -4381,5 +4375,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.intentions.mps b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.intentions.mps
new file mode 100644
index 000000000..81075bdb0
--- /dev/null
+++ b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.intentions.mps
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.structure.mps b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.structure.mps
index 118e9d192..21586be17 100644
--- a/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.structure.mps
+++ b/code/language/languages/org.fbme.ide.iec61499.lang/models/org.fbme.ide.iec61499.lang.structure.mps
@@ -1575,5 +1575,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/language/languages/org.fbme.ide.iec61499.lang/org.fbme.ide.iec61499.lang.mpl b/code/language/languages/org.fbme.ide.iec61499.lang/org.fbme.ide.iec61499.lang.mpl
index 9304586c9..5e19666f5 100644
--- a/code/language/languages/org.fbme.ide.iec61499.lang/org.fbme.ide.iec61499.lang.mpl
+++ b/code/language/languages/org.fbme.ide.iec61499.lang/org.fbme.ide.iec61499.lang.mpl
@@ -73,6 +73,7 @@
1db6de07-b355-4c0f-9979-75b4ac1e8215(org.fbme.lib)
ce018f97-56b9-4ee7-9b5f-2d462b6628bf(org.fbme.platform.lib)
d7eb0a2a-bd50-4576-beae-e4a89db35f20(jetbrains.mps.lang.scopes.runtime)
+ 1ed103c3-3aa6-49b7-9c21-6765ee11f224(MPS.Editor)
@@ -125,7 +126,10 @@
+
+
+
diff --git a/code/language/languages/org.fbme.ide.st.lang/models/org.fbme.ide.st.lang.editor.mps b/code/language/languages/org.fbme.ide.st.lang/models/org.fbme.ide.st.lang.editor.mps
index bb696715c..f87885d00 100644
--- a/code/language/languages/org.fbme.ide.st.lang/models/org.fbme.ide.st.lang.editor.mps
+++ b/code/language/languages/org.fbme.ide.st.lang/models/org.fbme.ide.st.lang.editor.mps
@@ -201,7 +201,6 @@
-
@@ -851,12 +850,8 @@
-
+
-
-
-
-
diff --git a/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.adapter.interfacepart.mps b/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.adapter.interfacepart.mps
index 5a040de71..27717cb54 100644
--- a/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.adapter.interfacepart.mps
+++ b/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.adapter.interfacepart.mps
@@ -107,6 +107,7 @@
+
@@ -7660,5 +7661,395 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.repository.mps b/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.repository.mps
index e64069bfc..b972c36e3 100644
--- a/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.repository.mps
+++ b/code/language/solutions/org.fbme.ide.iec61499.adapter/models/org.fbme.ide.iec61499.repository.mps
@@ -93,6 +93,9 @@
+
+
+
@@ -307,6 +310,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4204,6 +4294,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code/language/src/main/kotlin/org/fbme/ide/iec61499/repository/PlatformDeclarationsScope.kt b/code/language/src/main/kotlin/org/fbme/ide/iec61499/repository/PlatformDeclarationsScope.kt
index 82038c66c..6e04737b8 100644
--- a/code/language/src/main/kotlin/org/fbme/ide/iec61499/repository/PlatformDeclarationsScope.kt
+++ b/code/language/src/main/kotlin/org/fbme/ide/iec61499/repository/PlatformDeclarationsScope.kt
@@ -18,6 +18,10 @@ internal class PlatformDeclarationsScope(
return findNode(identifier)?.let { repository.adapterOrNull(it) }
}
+ override fun findCATBlockTypeDeclaration(identifier: Identifier): CATBlockTypeDeclaration? {
+ return findNode(identifier)?.let {repository.getAdapter(it, CATBlockTypeDeclaration::class.java)}
+ }
+
override fun findBasicFBTypeDeclaration(identifier: Identifier): BasicFBTypeDeclaration? {
return findNode(identifier)?.let { repository.adapterOrNull(it) }
}
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/DeclarationsScope.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/DeclarationsScope.kt
index 3e35d940a..73f634785 100644
--- a/code/library/src/main/kotlin/org/fbme/lib/iec61499/DeclarationsScope.kt
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/DeclarationsScope.kt
@@ -6,6 +6,7 @@ import org.fbme.lib.iec61499.fbnetwork.FunctionBlockDeclaration
interface DeclarationsScope {
fun findCompositeFBTypeDeclaration(identifier: Identifier): CompositeFBTypeDeclaration?
+ fun findCATBlockTypeDeclaration(identifier: Identifier): CATBlockTypeDeclaration?
fun findBasicFBTypeDeclaration(identifier: Identifier): BasicFBTypeDeclaration?
fun findServiceFBTypeDeclaration(identifier: Identifier): ServiceInterfaceFBTypeDeclaration?
fun findAdapterTypeDeclaration(identifier: Identifier): AdapterTypeDeclaration?
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/IEC61499Factory.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/IEC61499Factory.kt
index 5cf2d46dc..99f791479 100644
--- a/code/library/src/main/kotlin/org/fbme/lib/iec61499/IEC61499Factory.kt
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/IEC61499Factory.kt
@@ -18,6 +18,8 @@ interface IEC61499Factory {
fun createApplicationDeclaration(identifier: Identifier?): ApplicationDeclaration
fun createBasicFBTypeDeclaration(identifier: Identifier?): BasicFBTypeDeclaration
fun createCompositeFBTypeDeclaration(identifier: Identifier?): CompositeFBTypeDeclaration
+ fun createCATBlockTypeDeclaration(identifier: Identifier?): CATBlockTypeDeclaration
+ fun createHMIBlockTypeDeclaration(identifier: Identifier?): HMIInterfaceTypeDeclaration
fun createDeviceDeclaration(identifier: Identifier?): DeviceDeclaration
fun createDeviceTypeDeclaration(identifier: Identifier?): DeviceTypeDeclaration
fun createParameterAssignment(): ParameterAssignment
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/CATBlockTypeDeclaration.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/CATBlockTypeDeclaration.kt
new file mode 100644
index 000000000..84632a1d4
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/CATBlockTypeDeclaration.kt
@@ -0,0 +1,12 @@
+package org.fbme.lib.iec61499.declarations
+
+import org.fbme.lib.common.Declaration
+import org.fbme.lib.common.RootElement
+import org.fbme.lib.common.Reference
+
+
+interface CATBlockTypeDeclaration : Declaration, RootElement {
+ val hmiInterface: Reference
+ val blockDeclaration: Reference
+ var interfaceFileName: String
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/DependentFilesDefinition.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/DependentFilesDefinition.kt
new file mode 100644
index 000000000..4de6a8b2e
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/DependentFilesDefinition.kt
@@ -0,0 +1,5 @@
+package org.fbme.lib.iec61499.declarations
+
+interface DependentFilesDefinition {
+ var value: String
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/HMIInterfaceTypeDeclaration.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/HMIInterfaceTypeDeclaration.kt
new file mode 100644
index 000000000..8a4908a4f
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/HMIInterfaceTypeDeclaration.kt
@@ -0,0 +1,5 @@
+package org.fbme.lib.iec61499.declarations
+
+
+interface HMIInterfaceTypeDeclaration : FBTypeDeclaration{
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/SubCATDeclaration.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/SubCATDeclaration.kt
new file mode 100644
index 000000000..e123165a4
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/SubCATDeclaration.kt
@@ -0,0 +1,8 @@
+package org.fbme.lib.iec61499.declarations
+
+import org.fbme.lib.common.ContainedElement
+import org.fbme.lib.common.Declaration
+
+interface SubCATDeclaration: Declaration, ContainedElement {
+
+}
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/SymbolDefinition.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/SymbolDefinition.kt
new file mode 100644
index 000000000..da071c7f3
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/declarations/SymbolDefinition.kt
@@ -0,0 +1,5 @@
+package org.fbme.lib.iec61499.declarations
+
+interface SymbolDefinition {
+ var children: List
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/CATBlockTypeConverter.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/CATBlockTypeConverter.kt
new file mode 100644
index 000000000..29a275664
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/CATBlockTypeConverter.kt
@@ -0,0 +1,19 @@
+package org.fbme.lib.iec61499.parser
+
+import org.fbme.lib.common.Identifier
+import org.fbme.lib.common.Reference
+import org.fbme.lib.iec61499.declarations.CATBlockTypeDeclaration
+import org.fbme.lib.iec61499.declarations.CompositeFBTypeDeclaration
+import org.fbme.lib.iec61499.fbnetwork.FunctionBlockDeclaration
+
+class CATBlockTypeConverter(arguments: ConverterArguments) :
+ DeclarationConverterBase(arguments) {
+ override fun extractDeclarationBody(identifier: Identifier?): CATBlockTypeDeclaration {
+ checkNotNull(element)
+ val fbtd = factory.createCATBlockTypeDeclaration(identifier)
+ fbtd.blockDeclaration.setTargetName(element.getChild("Composite").getAttributeValue("Type"))
+ fbtd.hmiInterface.setTargetName(element.getChild("HMI").getAttributeValue("Type"))
+ fbtd.interfaceFileName = element.getChild("HMI").getAttributeValue("InterfaceFile")
+ return fbtd
+ }
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/HMIInterfaceConverter.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/HMIInterfaceConverter.kt
new file mode 100644
index 000000000..08b3bcab6
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/HMIInterfaceConverter.kt
@@ -0,0 +1,27 @@
+package org.fbme.lib.iec61499.parser
+
+import org.fbme.lib.common.Identifier
+import org.fbme.lib.common.Reference
+import org.fbme.lib.iec61499.declarations.CATBlockTypeDeclaration
+import org.fbme.lib.iec61499.declarations.CompositeFBTypeDeclaration
+import org.fbme.lib.iec61499.declarations.HMIInterfaceTypeDeclaration
+import org.fbme.lib.iec61499.fbnetwork.FunctionBlockDeclaration
+
+class HMIInterfaceConverter(arguments: ConverterArguments) :
+ DeclarationConverterBase(arguments) {
+ override fun extractDeclarationBody(identifier: Identifier?): HMIInterfaceTypeDeclaration {
+ checkNotNull(element)
+ val fbtd = factory.createHMIBlockTypeDeclaration(identifier)
+ val interfaceListElement = element.getChild("InterfaceList")
+ ParameterDeclarationConverter.extractAll(
+ with(interfaceListElement.getChild("InputVars")),
+ fbtd.inputParameters
+ )
+ ParameterDeclarationConverter.extractAll(
+ with(interfaceListElement.getChild("OutputVars")),
+ fbtd.outputParameters
+ )
+
+ return fbtd
+ }
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/RootConverter.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/RootConverter.kt
index d6d5e1139..cbbff2411 100644
--- a/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/RootConverter.kt
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/parser/RootConverter.kt
@@ -10,6 +10,9 @@ class RootConverter(
) {
fun convertFBType(): FBTypeDeclaration {
val root = myDocument.rootElement
+ if (root.getAttribute("UsedInCAT") != null && root.getAttribute("UsedInCAT").value == "True") {
+ return HMIInterfaceConverter(arguments()).extract()
+ }
if (root.getChild("FBNetwork") != null) {
return myConfiguration.createCompositeFbTypeConverter(arguments()).extract()
}
@@ -44,6 +47,10 @@ class RootConverter(
return SystemConverter(arguments()).extract()
}
+ fun convertCATConfiguration(): CATBlockTypeDeclaration {
+ return CATBlockTypeConverter(arguments()).extract()
+ }
+
private fun arguments(): ConverterArgumentsHolder {
return ConverterArgumentsHolder(
myConfiguration.entryFactory,
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/CATBlockTypePrinter.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/CATBlockTypePrinter.kt
new file mode 100644
index 000000000..15e06b1d6
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/CATBlockTypePrinter.kt
@@ -0,0 +1,30 @@
+package org.fbme.lib.iec61499.stringify
+
+import org.fbme.lib.iec61499.declarations.CATBlockTypeDeclaration
+import org.fbme.lib.iec61499.declarations.CompositeFBTypeDeclaration
+import org.fbme.lib.iec61499.fbnetwork.FunctionBlockDeclaration
+import org.jdom.Element
+
+class CATBlockTypePrinter(declaration: CATBlockTypeDeclaration) :
+ DeclarationPrinterBase(declaration, "CAT") {
+ override fun printDeclarationBody(element: Element) {
+ element.setAttribute("name", this.element.name)
+ element.addContent(CompositePrinter(this.element).print())
+ element.addContent(HMIPrinter(this.element).print())
+ }
+
+ private class CompositePrinter(fb: CATBlockTypeDeclaration) :
+ DeclarationPrinterBase(fb, "Composite") {
+ override fun printDeclarationBody(element: Element) {
+ element.setAttribute("Type", this.element.blockDeclaration.presentation)
+ }
+ }
+
+ private class HMIPrinter(fb: CATBlockTypeDeclaration) :
+ DeclarationPrinterBase(fb, "HMI") {
+ override fun printDeclarationBody(element: Element) {
+ element.setAttribute("Type", this.element.hmiInterface.presentation)
+ element.setAttribute("InterfaceFile", this.element.interfaceFileName)
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/DependentDeclarationGenerator.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/DependentDeclarationGenerator.kt
new file mode 100644
index 000000000..d66920d59
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/DependentDeclarationGenerator.kt
@@ -0,0 +1,39 @@
+package org.fbme.lib.iec61499.stringify
+
+import org.fbme.lib.common.Declaration
+import org.fbme.lib.common.RootElement
+import org.fbme.lib.iec61499.declarations.CATBlockTypeDeclaration
+import org.fbme.lib.iec61499.declarations.FBTypeDeclaration
+import org.fbme.lib.iec61499.declarations.HMIInterfaceTypeDeclaration
+import org.fbme.lib.iec61499.parser.ConverterArguments
+import org.fbme.lib.iec61499.parser.Iec61499ConverterConfiguration
+
+class DependentDeclarationGenerator(private val myDeclaration: Declaration, private val converterArguments: Iec61499ConverterConfiguration) {
+
+
+ fun generate(): List {
+ val rootElements: List = when (myDeclaration) {
+ is HMIInterfaceTypeDeclaration -> HMIInterfaceTypeGenerator(myDeclaration, converterArguments).generateDependents()
+ else -> listOf()
+ }
+
+
+ return rootElements
+ }
+
+ fun getName(): String {
+ val name = when (myDeclaration) {
+ is HMIInterfaceTypeDeclaration -> HMIInterfaceTypeGenerator.getDeclarationName(myDeclaration.name)
+ else -> myDeclaration.name
+ }
+ return name
+ }
+
+ fun getIdentifier(): String {
+ val name = when (myDeclaration) {
+ is HMIInterfaceTypeDeclaration -> HMIInterfaceTypeGenerator.getDeclarationName(myDeclaration.identifier.toString())
+ else -> myDeclaration.name
+ }
+ return name
+ }
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/HMIBlockPrinter.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/HMIBlockPrinter.kt
new file mode 100644
index 000000000..cf653481b
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/HMIBlockPrinter.kt
@@ -0,0 +1,23 @@
+package org.fbme.lib.iec61499.stringify
+
+import org.fbme.lib.iec61499.declarations.HMIInterfaceTypeDeclaration
+import org.fbme.lib.iec61499.parser.Iec61499ConverterConfiguration
+import org.jdom.Element
+
+class HMIBlockPrinter(declaration: HMIInterfaceTypeDeclaration) :
+ DeclarationPrinterBase(declaration, "HMIDeclaration") {
+
+// val factory = converterArguments.entryFactory
+// val stFactory = converterArguments.stEntryFactory
+ override fun printDeclarationBody(element: Element) {
+ element.addContent(FBInterfacePrinterWithAdapters(this.element).print())
+// val cFB = CompositeFBTypePrinter(HMIInterfaceTypeGenerator.generateComposite(factory, stFactory, this.element)).print().children
+// for (c in cFB) {
+// element.addContent(c.clone().detach())
+// }
+ addNullableContent(element, ParameterDeclarationPrinter.printAll("InputVars", this.element.inputParameters))
+ addNullableContent(element, ParameterDeclarationPrinter.printAll("OutputVars", this.element.outputParameters))
+ element.setAttribute("UsedInCAT", "True")
+ }
+
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/HMIInterfaceTypeGenerator.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/HMIInterfaceTypeGenerator.kt
new file mode 100644
index 000000000..6224a7243
--- /dev/null
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/HMIInterfaceTypeGenerator.kt
@@ -0,0 +1,469 @@
+package org.fbme.lib.iec61499.stringify
+
+import org.fbme.lib.common.Identifier
+import org.fbme.lib.iec61499.IEC61499Factory
+import org.fbme.lib.iec61499.declarations.*
+import org.fbme.lib.iec61499.fbnetwork.EntryKind
+import org.fbme.lib.iec61499.fbnetwork.FunctionBlockDeclaration
+import org.fbme.lib.iec61499.parser.Iec61499ConverterConfiguration
+import org.fbme.lib.iec61499.parser.STConverter
+import org.fbme.lib.st.STFactory
+import org.fbme.lib.st.expressions.Expression
+import org.fbme.lib.st.expressions.Literal
+import org.fbme.lib.st.statements.Statement
+import org.fbme.lib.st.types.DataType
+import org.fbme.lib.st.types.ElementaryType
+import java.util.function.BiFunction
+
+class HMIInterfaceTypeGenerator(val declaration: HMIInterfaceTypeDeclaration, val converterArguments: Iec61499ConverterConfiguration) {
+
+ val factory = converterArguments.entryFactory
+ val stFactory = converterArguments.stEntryFactory
+
+ fun generateDependents(): List {
+ val elements = mutableListOf()
+ val name = getDeclarationName(declaration.name)
+ val identifier = declaration.identifier.toString()
+ if (declaration.inputParameters.size > 0) {
+ val outFb = generateDispatchOut(factory, stFactory, declaration.inputParameters, name, identifier)
+ elements.add(outFb)
+ }
+ if (declaration.outputParameters.size > 0) {
+ val inFb = generateDispatchIn(
+ factory,
+ stFactory,
+ declaration.outputParameters,
+ name,
+ identifier
+ )
+ elements.add(inFb)
+ }
+ val compositeHMI = generateComposite(factory, stFactory, declaration, identifier)
+ elements.add(compositeHMI)
+ return elements
+ }
+
+
+companion object {
+ val CONNECTION_TYPES = listOf(
+ ElementaryType.BOOL,
+ ElementaryType.INT,
+ ElementaryType.REAL,
+ ElementaryType.LREAL,
+ ElementaryType.STRING
+ )
+
+ fun generateDispatchOut(factory: IEC61499Factory, stFactory: STFactory, outputVars: List, name: String = "", identifier: String = ""): FBTypeDeclaration {
+ val bfb = factory.createBasicFBTypeDeclaration(null)
+ bfb.name = "DISPATCH_OUT_${name}"
+
+ val startState = factory.createStateDeclaration(null)
+ startState.name = "START"
+ bfb.ecc.states.add(startState)
+
+ val nameDeclaration = generateParameterDeclaration(factory, "NAME", ElementaryType.STRING, listOf())
+ val mappingDeclaration = generateParameterDeclaration(factory, "MAPPING", ElementaryType.STRING, listOf())
+ mappingDeclaration.initialValue = STConverter.parseLiteral(stFactory, identifier)
+ bfb.inputParameters.add(mappingDeclaration)
+ bfb.outputParameters.add(nameDeclaration)
+
+ val outConnections = generateTypedConnections(factory, listOf(), CONNECTION_TYPES)
+ bfb.outputParameters.addAll(outConnections)
+ val typedEventsMap = mutableMapOf()
+ outConnections.forEach {
+ val typedEvent = factory.createEventDeclaration(null)
+ typedEvent.name = "IS_${it.type}"
+ val assoc = factory.createEventAssociation()
+ assoc.parameterReference.setTarget(it)
+ typedEvent.associations.add(assoc)
+
+ val nameAssoc = factory.createEventAssociation()
+ nameAssoc.parameterReference.setTarget(nameDeclaration)
+ typedEvent.associations.add(nameAssoc)
+ bfb.outputEvents.add(typedEvent)
+ typedEventsMap.put(it.type!!, typedEvent)
+ }
+
+ for (iV in outputVars) {
+ val state = factory.createStateDeclaration(null)
+ state.name = "SET_${iV.name}"
+ val action = factory.createStateAction()
+ val event = factory.createEventDeclaration(null)
+ event.name = "IS_${iV.name}"
+ val mappingAssoc = factory.createEventAssociation()
+ mappingAssoc.parameterReference.setTarget(mappingDeclaration)
+ event.associations.add(mappingAssoc)
+ val currParameter = generateParameterDeclaration(factory, iV.name, iV.type, listOf(event))
+ currParameter.initialValue = iV.initialValue
+ bfb.inputParameters.add(currParameter)
+ bfb.inputEvents.add(event)
+ val algorithm = factory.createAlgorithmDeclaration(null)
+ algorithm.name = "set${iV.name}"
+ val algorithmBody = factory.createAlgorithmBody(AlgorithmLanguage.ST)
+ val outCode = generateOutCode(iV, algorithm, factory, stFactory)
+ algorithmBody.statements.addAll(outCode)
+ algorithm.body = algorithmBody
+ action.algorithm.setTarget(algorithm)
+ bfb.algorithms.add(algorithm)
+ state.actions.add(action)
+ bfb.ecc.states.add(state)
+
+ val fromStartTransition = factory.createStateTransition()
+ fromStartTransition.condition.eventReference.setFQName("IS_${iV.name}")
+ fromStartTransition.sourceReference.setTarget(startState)
+ fromStartTransition.targetReference.setTarget(state)
+ bfb.ecc.transitions.add(fromStartTransition)
+ val toStartTransition = factory.createStateTransition()
+ toStartTransition.sourceReference.setTarget(state)
+ toStartTransition.targetReference.setTarget(startState)
+ bfb.ecc.transitions.add(toStartTransition)
+ }
+
+ return bfb
+ }
+
+
+ fun generateDispatchIn(factory: IEC61499Factory, stFactory: STFactory, inputVars: List, name: String = "", identifier: String = ""): FBTypeDeclaration {
+ val bfb = factory.createBasicFBTypeDeclaration(null)
+ bfb.name = "DISPATCH_IN_${name}"
+ val startState = factory.createStateDeclaration(null)
+ startState.name = "START"
+ bfb.ecc.states.add(startState)
+ val reqEvent = factory.createEventDeclaration(null)
+ reqEvent.name = "REQ"
+ bfb.inputEvents.add(reqEvent)
+ val inConnections = generateTypedConnections(factory, listOf(reqEvent), CONNECTION_TYPES)
+ val nameDeclaration = generateParameterDeclaration(factory, "NAME", ElementaryType.STRING, listOf(reqEvent))
+ val mappingDeclaration = generateParameterDeclaration(factory, "MAPPING", ElementaryType.STRING, listOf(reqEvent))
+ mappingDeclaration.initialValue = STConverter.parseLiteral(stFactory, identifier)
+ bfb.inputParameters.addAll(inConnections)
+ bfb.inputParameters.add(nameDeclaration)
+ bfb.inputParameters.add(mappingDeclaration)
+ for (iV in inputVars) {
+ if (iV.name == "MAPPING") {
+ continue
+ }
+
+ val event = factory.createEventDeclaration(null)
+ val eventAssociation = factory.createEventAssociation()
+
+ val state = factory.createStateDeclaration(null)
+ state.name = "SET_${iV.name}"
+ val action = factory.createStateAction()
+ val currParameter = factory.createParameterDeclaration(null)
+ currParameter.name = iV.name
+ currParameter.type = iV.type
+ currParameter.initialValue = iV.initialValue
+ bfb.outputParameters.add(currParameter)
+ eventAssociation.parameterReference.setTarget(currParameter)
+ event.name = "IS_${iV.name}"
+ event.associations.add(eventAssociation)
+ bfb.outputEvents.add(event)
+ val algorithm = factory.createAlgorithmDeclaration(null)
+ algorithm.name = "set${iV.name}"
+ val algorithmBody = factory.createAlgorithmBody(AlgorithmLanguage.ST)
+ val outCode = generateInCode(iV, algorithm, factory, stFactory)
+ algorithmBody.statements.addAll(outCode)
+ algorithm.body = algorithmBody
+ action.algorithm.setTarget(algorithm)
+ bfb.algorithms.add(algorithm)
+ state.actions.add(action)
+ bfb.ecc.states.add(state)
+ val fromStartTransition = factory.createStateTransition()
+ fromStartTransition.condition.setGuardCondition(generateInGuard(iV, stFactory))
+ fromStartTransition.sourceReference.setTarget(startState)
+ fromStartTransition.targetReference.setTarget(state)
+ bfb.ecc.transitions.add(fromStartTransition)
+ val toStartTransition = factory.createStateTransition()
+ toStartTransition.sourceReference.setTarget(state)
+ toStartTransition.targetReference.setTarget(startState)
+ bfb.ecc.transitions.add(toStartTransition)
+ }
+
+ return bfb
+ }
+
+ fun generateTypedConnections(factory: IEC61499Factory, events: List, types: List): List {
+ val resTypes = mutableListOf()
+ types.forEach {
+ val p = factory.createParameterDeclaration(null)
+ p.type = it
+ p.name = "${p.type}_VALUE"
+ resTypes.add(p)
+ events.forEach {
+ val assoc = factory.createEventAssociation()
+ assoc.parameterReference.setTarget(p)
+ it.associations.add(assoc)
+ }
+ }
+ return resTypes
+ }
+
+ fun generateParameterDeclaration(factory: IEC61499Factory, name: String, type: DataType?, associatedEvents: List): ParameterDeclaration {
+ val p_ = factory.createParameterDeclaration(null)
+ p_.type = type
+ p_.name = name
+ associatedEvents.forEach {
+ val assoc = factory.createEventAssociation()
+ assoc.parameterReference.setTarget(p_)
+ it.associations.add(assoc)
+ }
+ return p_
+ }
+
+
+ fun generateCode(code: String, factory: IEC61499Factory, stFactory: STFactory, algorithmDeclaration: AlgorithmDeclaration): List {
+ val parameterCollector =
+ BiFunction { name: Identifier?, type: DataType? ->
+ val parameterDeclaration: ParameterDeclaration =
+ factory.createParameterDeclaration(name)
+ parameterDeclaration.type = type
+ algorithmDeclaration.temporaryVariables.add(parameterDeclaration)
+ Unit
+ }
+ return STConverter.parseStatementListWithDeclarations(
+ stFactory,
+ code,
+ { t, u -> parameterCollector.apply(t, u) }
+ )
+ }
+
+ fun generateOutCode(p: ParameterDeclaration, algorithmDeclaration: AlgorithmDeclaration, factory: IEC61499Factory, stFactory: STFactory): List {
+ val code = "VAR \n" +
+ "TAG: STRING;\n" +
+ "END_VAR;" +
+ "TAG:= '#${p.name}';\n" +
+ "NAME:=CONCAT(MAPPING, TAG);\n" +
+ "${p.type}_VALUE:=${p.name};]]>"
+ val statementList = generateCode(code, factory, stFactory, algorithmDeclaration)
+ return statementList
+ }
+
+ fun generateInCode(p: ParameterDeclaration, algorithmDeclaration: AlgorithmDeclaration, factory: IEC61499Factory, stFactory: STFactory): List {
+ val code = "${p.name}:= ${p.type!!.stringify()}_VALUE;"
+
+ return generateCode(code, factory, stFactory, algorithmDeclaration)
+ }
+
+ fun generateInGuard(p: ParameterDeclaration, stFactory: STFactory): Expression {
+ val code = "(LEFT(NAME, LEN(NAME) - ${p.name.length + 2}) = MAPPING) AND (RIGHT(NAME, LEN(NAME) - LEN(NAME) + ${p.name.length + 1}) = '#${p.name}')"
+ return STConverter.parseExpression(stFactory, code)!!
+ }
+
+ fun getDeclarationName(name: String): String {
+ if (name.length < 5) {
+ return name
+ }
+ if (name.endsWith("_HMI")) {
+ return name.take(name.length - 4)
+ }
+ if (name.length < 9) {
+ return name
+ }
+ if (name.endsWith("_HMI_CONF")) {
+ return name.take(name.length - 9)
+ }
+ return name
+ }
+
+ fun generateComposite(factory: IEC61499Factory, stFactory: STFactory, declaration: HMIInterfaceTypeDeclaration, identifier: String = ""): CompositeFBTypeDeclaration {
+ var cFB = factory.createCompositeFBTypeDeclaration(null)
+ val targetBlockName = getDeclarationName(declaration.name)
+ cFB.name = targetBlockName + "_HMI"
+ declaration.inputParameters.forEach {
+ if (it.name != "MAPPING") {
+ val pD = factory.createParameterDeclaration(null)
+ pD.name = it.name
+ pD.type = it.type
+ pD.initialValue = it.initialValue
+ cFB.inputParameters.add(pD)
+ }
+ }
+ declaration.outputParameters.forEach {
+ val pD = factory.createParameterDeclaration(null)
+ pD.name = it.name
+ pD.type = it.type
+ pD.initialValue = it.initialValue
+ cFB.outputParameters.add(pD)
+ }
+
+ val initEvent = factory.createEventDeclaration(null)
+ initEvent.name = "INIT"
+ initEvent.associations
+ val mappingInput = factory.createParameterDeclaration(null)
+ mappingInput.name = "MAPPING"
+ mappingInput.type = ElementaryType.STRING
+ mappingInput.initialValue = STConverter.parseLiteral(stFactory, identifier)
+ cFB.inputParameters.add(mappingInput)
+ cFB.inputEvents.add(initEvent)
+
+ if (cFB.inputParameters.size - 1 > 0) {
+// NEEDED FUNCTION BLOCKS GENERATION
+
+ cFB.network.functionBlocks.add(generateCommunicationBlock("PUBLISH_1", factory, stFactory))
+ cFB.network.functionBlocks.add(generateFunctionDeclarationNoParam("JSON_SERIALIZER", factory))
+ cFB.network.functionBlocks.add(generateFunctionDeclarationNoParam("DISPATCH_OUT_$targetBlockName", factory))
+
+// EVENTS GENERATION
+
+ val cEInitPublish = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cEInitPublish.sourceReference.setFQName("INIT")
+ cEInitPublish.targetReference.setFQName("PUBLISH_1.INIT")
+ cFB.network.eventConnections.add(cEInitPublish)
+
+ val cESerializerPublish = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cESerializerPublish.sourceReference.setFQName("JSON_SERIALIZER.RES")
+ cESerializerPublish.targetReference.setFQName("PUBLISH_1.REQ")
+ cFB.network.eventConnections.add(cESerializerPublish)
+
+ declaration.inputParameters.stream().filter{it.name != "MAPPING"}
+ .forEach{
+ val event = generateEventForParameter(it, factory)
+ cFB.inputEvents.add(event)
+ val cEDispatch = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cEDispatch.sourceReference.setFQName(event.name)
+ cEDispatch.targetReference.setFQName("DISPATCH_OUT_$targetBlockName.${event.name}")
+ cFB.network.eventConnections.add(cEDispatch)
+ }
+
+// DATA CONNECTIONS GENERATION
+
+ val cDSerializerPublish = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDSerializerPublish.sourceReference.setFQName("JSON_SERIALIZER.MSG")
+ cDSerializerPublish.targetReference.setFQName("PUBLISH_1.SD_1")
+ cFB.network.dataConnections.add(cDSerializerPublish)
+
+ declaration.inputParameters.stream()
+ .forEach{
+ val cDDispatch = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDDispatch.sourceReference.setFQName(it.name)
+ cDDispatch.targetReference.setFQName("DISPATCH_OUT_$targetBlockName.${it.name}")
+ cFB.network.dataConnections.add(cDDispatch)
+ }
+
+ val cDNameSerialize = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDNameSerialize.sourceReference.setFQName("DISPATCH_OUT_$targetBlockName.NAME")
+ cDNameSerialize.targetReference.setFQName("JSON_SERIALIZER.NAME")
+ cFB.network.dataConnections.add(cDNameSerialize)
+
+// CONNECTIONS FOR DIFFERENT DATA TYPES
+
+ HMIInterfaceTypeGenerator.CONNECTION_TYPES.forEach {
+ val cEDispatch = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cEDispatch.sourceReference.setFQName("DISPATCH_OUT_$targetBlockName.IS_${it.name}")
+ cEDispatch.targetReference.setFQName("JSON_SERIALIZER.IS_${it.name}")
+ cFB.network.eventConnections.add(cEDispatch)
+ val cDDispatch = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDDispatch.sourceReference.setFQName("DISPATCH_OUT_$targetBlockName.${it.name}_VALUE")
+ cDDispatch.targetReference.setFQName("JSON_SERIALIZER.${it.name}_VALUE")
+ cFB.network.dataConnections.add(cDDispatch)
+ }
+
+ }
+
+ if (declaration.outputParameters.size > 0) {
+// NEEDED FUNCTION BLOCKS GENERATION
+
+ cFB.network.functionBlocks.add(generateCommunicationBlock("SUBSCRIBE_1", factory, stFactory, 65012))
+ cFB.network.functionBlocks.add(generateFunctionDeclarationNoParam("JSON_DESERIALIZER", factory))
+ cFB.network.functionBlocks.add(generateFunctionDeclarationNoParam("DISPATCH_IN_$targetBlockName", factory))
+
+// EVENTS GENERATION
+
+ val cEInitSubscribe = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cEInitSubscribe.sourceReference.setFQName("INIT")
+ cEInitSubscribe.targetReference.setFQName("SUBSCRIBE_1.INIT")
+ cFB.network.eventConnections.add(cEInitSubscribe)
+
+ val cESubscribeDeserialize = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cESubscribeDeserialize.sourceReference.setFQName("SUBSCRIBE_1.IND")
+ cESubscribeDeserialize.targetReference.setFQName("JSON_DESERIALIZER.REQ")
+ cFB.network.eventConnections.add(cESubscribeDeserialize)
+
+ val cEDeserializeDispatch = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cEDeserializeDispatch.sourceReference.setFQName("JSON_DESERIALIZER.RES")
+ cEDeserializeDispatch.targetReference.setFQName("DISPATCH_IN_$targetBlockName.REQ")
+ cFB.network.eventConnections.add(cEDeserializeDispatch)
+
+ declaration.outputParameters.forEach {
+ val event = generateEventForParameter(it, factory)
+ cFB.outputEvents.add(event)
+
+ val cEDispatchRes = factory.createFBNetworkConnection(EntryKind.EVENT)
+ cEDispatchRes.sourceReference.setFQName("DISPATCH_IN_$targetBlockName.${event.name}")
+ cEDispatchRes.targetReference.setFQName(event.name)
+ cFB.network.eventConnections.add(cEDispatchRes)
+ }
+
+// DATA GENERATION
+
+ val cDSubscribeDeserialize = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDSubscribeDeserialize.sourceReference.setFQName("SUBSCRIBE_1.RD_1")
+ cDSubscribeDeserialize.targetReference.setFQName("JSON_DESERIALIZER.DATA")
+ cFB.network.dataConnections.add(cDSubscribeDeserialize)
+
+ val cDDeserializeName = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDDeserializeName.sourceReference.setFQName("JSON_DESERIALIZER.NAME")
+ cDDeserializeName.targetReference.setFQName("DISPATCH_IN_$targetBlockName.NAME")
+ cFB.network.dataConnections.add(cDDeserializeName)
+
+ val cDMappingDispatch = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDMappingDispatch.sourceReference.setFQName("MAPPING")
+ cDMappingDispatch.targetReference.setFQName("DISPATCH_IN_$targetBlockName.MAPPING")
+ cFB.network.dataConnections.add(cDMappingDispatch)
+
+ declaration.outputParameters.forEach {
+ val cEDispatchRes = factory.createFBNetworkConnection(EntryKind.DATA)
+ cEDispatchRes.sourceReference.setFQName("DISPATCH_IN_$targetBlockName.${it.name}")
+ cEDispatchRes.targetReference.setFQName(it.name)
+ cFB.network.dataConnections.add(cEDispatchRes)
+ }
+
+ HMIInterfaceTypeGenerator.CONNECTION_TYPES.forEach {
+ val cDDispatch = factory.createFBNetworkConnection(EntryKind.DATA)
+ cDDispatch.sourceReference.setFQName("JSON_DESERIALIZER.${it.name}_VALUE")
+ cDDispatch.targetReference.setFQName("DISPATCH_IN_$targetBlockName.${it.name}_VALUE")
+ cFB.network.dataConnections.add(cDDispatch)
+ }
+ }
+
+
+ return cFB
+ }
+
+ fun generateEventForParameter(parameter: ParameterDeclaration, factory: IEC61499Factory): EventDeclaration {
+ val currEvent = factory.createEventDeclaration(null)
+ currEvent.name = "IS_${parameter.name}"
+ val assoc = factory.createEventAssociation()
+ assoc.parameterReference.setTarget(parameter)
+ currEvent.associations.add(assoc)
+ return currEvent
+ }
+
+ fun generateCommunicationBlock(name: String, factory: IEC61499Factory, stFactory: STFactory, port: Int = 65011): FunctionBlockDeclaration {
+ val fB = factory.createFunctionBlockDeclaration(null)
+ fB.name = name
+ val host = factory.createParameterAssignment()
+ host.parameterReference.setTargetName("ID")
+ host.value = STConverter.parseLiteral(stFactory, "\"225.0.0.2:${port}\"")
+ fB.parameters.add(host)
+
+
+ val qi = factory.createParameterAssignment()
+ qi.parameterReference.setTargetName("QI")
+ qi.value = STConverter.parseLiteral(stFactory, "1")
+ fB.parameters.add(qi)
+
+ fB.typeReference.setTargetName(name)
+ return fB
+ }
+
+ fun generateFunctionDeclarationNoParam(name: String, factory: IEC61499Factory): FunctionBlockDeclaration {
+ val fB = factory.createFunctionBlockDeclaration(null)
+ fB.name = name
+ fB.typeReference.setTargetName(name)
+ return fB
+ }
+}
+
+}
\ No newline at end of file
diff --git a/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/RootDeclarationPrinter.kt b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/RootDeclarationPrinter.kt
index 948987ec4..f0c5a2dfa 100644
--- a/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/RootDeclarationPrinter.kt
+++ b/code/library/src/main/kotlin/org/fbme/lib/iec61499/stringify/RootDeclarationPrinter.kt
@@ -2,6 +2,8 @@ package org.fbme.lib.iec61499.stringify
import org.fbme.lib.common.Declaration
import org.fbme.lib.iec61499.declarations.*
+import org.fbme.lib.iec61499.parser.ConverterArguments
+import org.fbme.lib.iec61499.parser.Iec61499ConverterConfiguration
import org.jdom.DocType
import org.jdom.Document
import org.jdom.Element
@@ -12,6 +14,8 @@ class RootDeclarationPrinter(private val myDeclaration: Declaration) {
is AdapterTypeDeclaration -> AdapterTypePrinter(myDeclaration).print()
is BasicFBTypeDeclaration -> BasicFBTypePrinter(myDeclaration).print()
is CompositeFBTypeDeclaration -> CompositeFBTypePrinter(myDeclaration).print()
+ is CATBlockTypeDeclaration -> CATBlockTypePrinter(myDeclaration).print()
+ is HMIInterfaceTypeDeclaration -> HMIBlockPrinter(myDeclaration).print()
is DeviceTypeDeclaration -> DeviceTypePrinter(myDeclaration).print()
is ResourceTypeDeclaration -> ResourceTypePrinter(myDeclaration).print()
is ServiceInterfaceFBTypeDeclaration -> ServiceInterfaceFBTypePrinter(myDeclaration).print()
diff --git a/code/nxt-integration/solutions/org.fbme.integration.nxt/lib/nxt-integration.jar b/code/nxt-integration/solutions/org.fbme.integration.nxt/lib/nxt-integration.jar
new file mode 100644
index 000000000..b16206703
Binary files /dev/null and b/code/nxt-integration/solutions/org.fbme.integration.nxt/lib/nxt-integration.jar differ
diff --git a/samples/sandbox/solutions/org.fbme.ide.eccSandbox/models/org.fbme.ide.eccSandbox/null.fbt b/samples/sandbox/solutions/org.fbme.ide.eccSandbox/models/org.fbme.ide.eccSandbox/null.fbt
new file mode 100644
index 000000000..a5c51024e
--- /dev/null
+++ b/samples/sandbox/solutions/org.fbme.ide.eccSandbox/models/org.fbme.ide.eccSandbox/null.fbt
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/sandbox/solutions/org.fbme.ide.sandbox/models/org.fbme.ide.iec61499.lang.sandbox.mpsPersistence.mps b/samples/sandbox/solutions/org.fbme.ide.sandbox/models/org.fbme.ide.iec61499.lang.sandbox.mpsPersistence.mps
index 67b9e3804..d0501c7f4 100644
--- a/samples/sandbox/solutions/org.fbme.ide.sandbox/models/org.fbme.ide.iec61499.lang.sandbox.mpsPersistence.mps
+++ b/samples/sandbox/solutions/org.fbme.ide.sandbox/models/org.fbme.ide.iec61499.lang.sandbox.mpsPersistence.mps
@@ -1532,5 +1532,11 @@
+
+
+
+
+
+
diff --git a/samples/statistics-plugin/solutions/org.fbme.samples.statisticsPlugin/lib/statistics-plugin.jar b/samples/statistics-plugin/solutions/org.fbme.samples.statisticsPlugin/lib/statistics-plugin.jar
new file mode 100644
index 000000000..a57506d01
Binary files /dev/null and b/samples/statistics-plugin/solutions/org.fbme.samples.statisticsPlugin/lib/statistics-plugin.jar differ
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 14f191ebb..979cf2ffc 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,20 +1,21 @@
rootProject.name = "FBME"
include(
- "code:4diac-integration",
- "code:enas",
- "code:language",
- "code:library",
- "code:nxt-integration",
- "code:platform",
- "code:richediting",
- "code:scenes",
- "code:smv-debugger",
- "code:debugger",
+"code:4diac-integration",
+"code:enas",
+"code:language",
+"code:library",
+"code:nxt-integration",
+"code:platform",
+"code:richediting",
+"code:scenes",
+"code:smv-debugger",
+"code:debugger",
- "docs",
+"docs",
- "samples:statistics-plugin",
- "samples:sandbox",
- "samples:smv-debugger"
+"samples:statistics-plugin",
+"samples:sandbox",
+"samples:smv-debugger",
+"cat_visual"
)
\ No newline at end of file
diff --git a/solutions/WaterTank/WaterTank.msd b/solutions/WaterTank/WaterTank.msd
new file mode 100644
index 000000000..c098be686
--- /dev/null
+++ b/solutions/WaterTank/WaterTank.msd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ b8a7e14f-52ea-4ee2-b17e-26c27da8084c(IEC-61499)
+ 5aff85f5-c1e8-49b6-a1f1-66d79702cceb(org.fbme.ide.iec61499.adapter)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/solutions/WaterTank/models/WaterTank.water_tank.mps b/solutions/WaterTank/models/WaterTank.water_tank.mps
new file mode 100644
index 000000000..29796e363
--- /dev/null
+++ b/solutions/WaterTank/models/WaterTank.water_tank.mps
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+