Compare commits

..

No commits in common. "fd5ff5e30ca7ff2d1f8914ce58063638ae5bc267" and "6ce1e68b866ad56fb18aa5299b372108f4d32caf" have entirely different histories.

274 changed files with 5775 additions and 10717 deletions

2
.gitignore vendored
View File

@ -3,10 +3,8 @@
*.iws
out/
.gradle
.kotlin
build/
data/
.kotlin/
!gradle-wrapper.jar

4
.space.kts Normal file
View File

@ -0,0 +1,4 @@
job("Build") {
gradlew("openjdk:11", "build")
}

View File

@ -1,54 +1,12 @@
# Changelog
## Unreleased
## [Unreleased]
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
## 0.4.1 - 2024-03-15
### Changed
- VisionProperties `flowChanges()` -> `changes`
### Fixed
- Bug with ElementVisionRenderer having the same name
- Plotly update problem
## 0.4.0 - 2024-02-16
### Added
- Added compose-mpp rendering.
### Changed
- **Breaking API** Move vision cache to upper level for renderers to avoid re-creating visions for page reload.
- **Breaking API** Forms refactor.
- **Breaking API** Migrated from React to Compose-html.
- **Breaking API** changed js package for `visionforge-core` to `space.kscience.visionforge.html` to avoid mixing html and generic parts.
## 0.3.0 - 2023-12-23
### Added
- Context receivers flag
- MeshLine for thick lines
- Custom client-side events and thier processing in VisionServer
- Control/input visions
### Changed
- Color accessor property is now `colorProperty`. Color uses non-nullable `invoke` instead of `set`.
- API update for server and pages
- Edges moved to solids module for easier construction
@ -59,14 +17,17 @@
- Naming of Canvas3D options.
- Lights are added to the scene instead of 3D options.
### Fixed
### Deprecated
### Removed
### Fixed
- Jupyter integration for IDEA and Jupyter lab.
## 0.2.0
### Security
## [0.2.0]
### Added
- Server module
- Change collector
- Customizable accessors for colors
@ -77,8 +38,8 @@
- Markdown module
- Tables module
### Changed
### Changed
- Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate.
- Point3D and Point2D are made separate classes instead of expect/actual (to split up different engines.
- JavaFX support moved to a separate module
@ -93,10 +54,16 @@
- Property listeners are not triggered if there are no changes.
- Feedback websocket connection in the client.
### Removed
### Deprecated
### Removed
- Primary modules dependencies on UI
### Fixed
### Fixed
- Version conflicts
### Security

158
README.md
View File

@ -61,96 +61,157 @@ To learn more about DataForge, please consult the following URLs:
## Modules contained in this repository
<hr/>
### [cern-root-loader](cern-root-loader)
* ### [cern-root-loader](cern-root-loader)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo](demo)
* ### [demo](demo)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [visionforge-compose-html](visionforge-compose-html)
* ### [jupyter](jupyter)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [visionforge-compose-multiplatform](visionforge-compose-multiplatform)
* ### [ui](ui)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [visionforge-core](visionforge-core)
* ### [visionforge-core](visionforge-core)
>
>
> **Maturity**: DEVELOPMENT
<hr/>
### [visionforge-gdml](visionforge-gdml)
* ### [visionforge-fx](visionforge-fx)
>
> **Maturity**: EXPERIMENTAL
### [visionforge-jupyter](visionforge-jupyter)
> Common visionforge jupyter module
>
> **Maturity**: EXPERIMENTAL
### [visionforge-markdown](visionforge-markdown)
>
> **Maturity**: EXPERIMENTAL
### [visionforge-plotly](visionforge-plotly)
>
> **Maturity**: EXPERIMENTAL
### [visionforge-server](visionforge-server)
>
> **Maturity**: EXPERIMENTAL
### [visionforge-solid](visionforge-solid)
>
> **Maturity**: DEVELOPMENT
### [visionforge-tables](visionforge-tables)
>
> **Maturity**: PROTOTYPE
<hr/>
### [visionforge-threejs](visionforge-threejs)
* ### [visionforge-gdml](visionforge-gdml)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/compose-desktop-demo](demo/compose-desktop-demo)
* ### [visionforge-markdown](visionforge-markdown)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/gdml](demo/gdml)
* ### [visionforge-plotly](visionforge-plotly)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/js-playground](demo/js-playground)
* ### [visionforge-server](visionforge-server)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/muon-monitor](demo/muon-monitor)
* ### [visionforge-solid](visionforge-solid)
>
>
> **Maturity**: DEVELOPMENT
<hr/>
* ### [visionforge-tables](visionforge-tables)
>
>
> **Maturity**: PROTOTYPE
<hr/>
* ### [visionforge-threejs](visionforge-threejs)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/playground](demo/playground)
* ### [gdml](demo/gdml)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/sat-demo](demo/sat-demo)
* ### [js-playground](demo/js-playground)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [demo/solid-showcase](demo/solid-showcase)
* ### [muon-monitor](demo/muon-monitor)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [visionforge-jupyter/visionforge-jupyter-common](visionforge-jupyter/visionforge-jupyter-common)
> Jupyter api artifact including all common modules
* ### [playground](demo/playground)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
### [visionforge-threejs/visionforge-threejs-server](visionforge-threejs/visionforge-threejs-server)
* ### [plotly-fx](demo/plotly-fx)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [sat-demo](demo/sat-demo)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [solid-showcase](demo/solid-showcase)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-jupyter-gdml](jupyter/visionforge-jupyter-gdml)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [bootstrap](ui/bootstrap)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [react](ui/react)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [ring](ui/ring)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
* ### [visionforge-threejs-server](visionforge-threejs/visionforge-threejs-server)
>
>
> **Maturity**: EXPERIMENTAL
<hr/>
**Class diagram:**
@ -222,21 +283,6 @@ Visualization example for geometry defined as GDML file.
![](docs/images/gdml-demo.png)
## Stability and documentation
VisionForge is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have the following levels:
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
with `@DFExperimental` or other stability warning annotations.
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
Additionally, one should note that the VisionForge Json format impacts the reproducibility of stored vision fragments. There should not be any breaks of the format between major releases. All problems should be reported.
The documentation for the project is a work in progress. Please report any issues with missing, vague or wrong information. The contributions into documentation are quite welcome.
## Thanks and references
The original three.js bindings were made by [Lars Ivar Hatledal](https://github.com/markaren), but the project is discontinued right now.

View File

@ -1,16 +1,18 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
import space.kscience.gradle.useApache2Licence
import space.kscience.gradle.useSPCTeam
plugins {
id("space.kscience.gradle.project")
id("org.jetbrains.kotlinx.kover") version "0.5.0"
// id("org.jetbrains.kotlinx.kover") version "0.5.0"
}
val dataforgeVersion by extra("0.8.0")
val dataforgeVersion by extra("0.6.2")
val fxVersion by extra("11")
allprojects {
group = "space.kscience"
version = "0.4.2-dev-2"
version = "0.3.0-dev-16"
}
subprojects {
@ -25,16 +27,16 @@ subprojects {
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
compilerOptions {
freeCompilerArgs.add("-Xcontext-receivers")
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers"
}
}
// tasks.withType<KotlinJsCompile>{
// kotlinOptions{
// useEsClasses = true
// }
// }
tasks.withType<KotlinJsCompile>{
kotlinOptions{
useEsClasses = true
}
}
}
ksciencePublish {

View File

@ -1,77 +1,3 @@
public final class ru/mipt/npm/root/BMN {
public static final field INSTANCE Lru/mipt/npm/root/BMN;
public final fun getJson ()Lkotlinx/serialization/json/Json;
public final fun readEventJson (Ljava/lang/String;)Lru/mipt/npm/root/BmnEventContainer;
}
public final class ru/mipt/npm/root/BMNKt {
public static final fun toVector (Lru/mipt/npm/root/FairTrackParam;)Lspace/kscience/visionforge/solid/Float32Vector3D;
}
public final class ru/mipt/npm/root/BmnEventContainer {
public fun <init> (Ljava/util/List;Ljava/util/List;)V
public final fun getBmnGlobalTracks ()Ljava/util/List;
public final fun getCbmTracks ()Ljava/util/List;
}
public final class ru/mipt/npm/root/BmnGlobalTrack {
public static final field Companion Lru/mipt/npm/root/BmnGlobalTrack$Companion;
public fun <init> (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)V
public final fun component1 ()Lru/mipt/npm/root/FairTrackParam;
public final fun component2 ()Lru/mipt/npm/root/FairTrackParam;
public final fun copy (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)Lru/mipt/npm/root/BmnGlobalTrack;
public static synthetic fun copy$default (Lru/mipt/npm/root/BmnGlobalTrack;Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;ILjava/lang/Object;)Lru/mipt/npm/root/BmnGlobalTrack;
public fun equals (Ljava/lang/Object;)Z
public final fun getFParamFirst ()Lru/mipt/npm/root/FairTrackParam;
public final fun getFParamLast ()Lru/mipt/npm/root/FairTrackParam;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class ru/mipt/npm/root/BmnGlobalTrack$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/BmnGlobalTrack$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/BmnGlobalTrack;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lru/mipt/npm/root/BmnGlobalTrack;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/BmnGlobalTrack$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/CbmStsTrack {
public static final field Companion Lru/mipt/npm/root/CbmStsTrack$Companion;
public fun <init> (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)V
public final fun component1 ()Lru/mipt/npm/root/FairTrackParam;
public final fun component2 ()Lru/mipt/npm/root/FairTrackParam;
public final fun copy (Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;)Lru/mipt/npm/root/CbmStsTrack;
public static synthetic fun copy$default (Lru/mipt/npm/root/CbmStsTrack;Lru/mipt/npm/root/FairTrackParam;Lru/mipt/npm/root/FairTrackParam;ILjava/lang/Object;)Lru/mipt/npm/root/CbmStsTrack;
public fun equals (Ljava/lang/Object;)Z
public final fun getFParamFirst ()Lru/mipt/npm/root/FairTrackParam;
public final fun getFParamLast ()Lru/mipt/npm/root/FairTrackParam;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class ru/mipt/npm/root/CbmStsTrack$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/CbmStsTrack$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/CbmStsTrack;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lru/mipt/npm/root/CbmStsTrack;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/CbmStsTrack$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/DGeoBoolNode : ru/mipt/npm/root/DObject {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFLeft ()Lru/mipt/npm/root/DGeoShape;
@ -80,28 +6,6 @@ public final class ru/mipt/npm/root/DGeoBoolNode : ru/mipt/npm/root/DObject {
public final fun getFRightMat ()Lru/mipt/npm/root/DGeoMatrix;
}
public class ru/mipt/npm/root/DGeoCombiTrans : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFRotation ()Lru/mipt/npm/root/DGeoRotation;
public final fun getFTranslation ()[D
}
public final class ru/mipt/npm/root/DGeoGenTrans : ru/mipt/npm/root/DGeoCombiTrans {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFScale ()[D
}
public final class ru/mipt/npm/root/DGeoHMatrix : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFRotation ()Lru/mipt/npm/root/DGeoRotation;
public final fun getFScale ()[D
public final fun getFTranslation ()[D
}
public final class ru/mipt/npm/root/DGeoIdentity : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
}
public final class ru/mipt/npm/root/DGeoManager : ru/mipt/npm/root/DNamed {
public static final field Companion Lru/mipt/npm/root/DGeoManager$Companion;
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
@ -119,8 +23,8 @@ public final class ru/mipt/npm/root/DGeoMaterial : ru/mipt/npm/root/DNamed {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
}
public abstract class ru/mipt/npm/root/DGeoMatrix : ru/mipt/npm/root/DNamed {
public synthetic fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public class ru/mipt/npm/root/DGeoMatrix : ru/mipt/npm/root/DNamed {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
}
public final class ru/mipt/npm/root/DGeoMedium : ru/mipt/npm/root/DNamed {
@ -134,12 +38,7 @@ public final class ru/mipt/npm/root/DGeoNode : ru/mipt/npm/root/DNamed {
public final fun getFVolume ()Lru/mipt/npm/root/DGeoVolume;
}
public final class ru/mipt/npm/root/DGeoRotation : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFRotationMatrix ()[D
}
public final class ru/mipt/npm/root/DGeoScale : ru/mipt/npm/root/DGeoMatrix {
public class ru/mipt/npm/root/DGeoScale : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFScale ()[D
public final fun getX ()D
@ -154,11 +53,6 @@ public final class ru/mipt/npm/root/DGeoShape : ru/mipt/npm/root/DNamed {
public final fun getFDZ ()D
}
public final class ru/mipt/npm/root/DGeoTranslation : ru/mipt/npm/root/DGeoMatrix {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFTranslation ()[D
}
public final class ru/mipt/npm/root/DGeoVolume : ru/mipt/npm/root/DNamed, space/kscience/dataforge/misc/Named {
public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lru/mipt/npm/root/DObjectCache;)V
public final fun getFFillColor ()Ljava/lang/Integer;
@ -200,45 +94,7 @@ public final class ru/mipt/npm/root/DObjectKt {
}
public final class ru/mipt/npm/root/DRootToSolidKt {
public static final fun rootGeo (Lspace/kscience/visionforge/MutableVisionContainer;Lru/mipt/npm/root/DGeoManager;Ljava/lang/String;IZ)Lspace/kscience/visionforge/solid/SolidGroup;
public static synthetic fun rootGeo$default (Lspace/kscience/visionforge/MutableVisionContainer;Lru/mipt/npm/root/DGeoManager;Ljava/lang/String;IZILjava/lang/Object;)Lspace/kscience/visionforge/solid/SolidGroup;
}
public final class ru/mipt/npm/root/FairTrackParam {
public static final field Companion Lru/mipt/npm/root/FairTrackParam$Companion;
public fun <init> (DDDDDD)V
public final fun component1 ()D
public final fun component2 ()D
public final fun component3 ()D
public final fun component4 ()D
public final fun component5 ()D
public final fun component6 ()D
public final fun copy (DDDDDD)Lru/mipt/npm/root/FairTrackParam;
public static synthetic fun copy$default (Lru/mipt/npm/root/FairTrackParam;DDDDDDILjava/lang/Object;)Lru/mipt/npm/root/FairTrackParam;
public fun equals (Ljava/lang/Object;)Z
public final fun getFQp ()D
public final fun getFTx ()D
public final fun getFTy ()D
public final fun getFX ()D
public final fun getFY ()D
public final fun getFZ ()D
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class ru/mipt/npm/root/FairTrackParam$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/FairTrackParam$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/FairTrackParam;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lru/mipt/npm/root/FairTrackParam;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class ru/mipt/npm/root/FairTrackParam$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
public static final fun toSolid (Lru/mipt/npm/root/DGeoManager;)Lspace/kscience/visionforge/solid/SolidGroup;
}
public final class ru/mipt/npm/root/RootColors {
@ -252,7 +108,7 @@ public final class ru/mipt/npm/root/serialization/JsonToRootKt {
}
public final class ru/mipt/npm/root/serialization/RootToSolidKt {
public static final fun rootGeo (Lspace/kscience/visionforge/MutableVisionContainer;Lru/mipt/npm/root/serialization/TGeoManager;)Lspace/kscience/visionforge/solid/SolidGroup;
public static final fun toSolid (Lru/mipt/npm/root/serialization/TGeoManager;)Lspace/kscience/visionforge/solid/SolidGroup;
}
public class ru/mipt/npm/root/serialization/TGeoBBox : ru/mipt/npm/root/serialization/TGeoShape {
@ -263,11 +119,12 @@ public class ru/mipt/npm/root/serialization/TGeoBBox : ru/mipt/npm/root/serializ
public final fun getFDY ()D
public final fun getFDZ ()D
public final fun getFOrigin ()[D
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoBBox;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoBBox;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoBBox$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoBBox$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoBBox;
@ -288,7 +145,7 @@ public abstract class ru/mipt/npm/root/serialization/TGeoBoolNode : ru/mipt/npm/
public final fun getFLeftMat ()Lru/mipt/npm/root/serialization/TGeoMatrix;
public abstract fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public final fun getFRightMat ()Lru/mipt/npm/root/serialization/TGeoMatrix;
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoBoolNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoBoolNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoBoolNode$Companion {
@ -297,14 +154,17 @@ public final class ru/mipt/npm/root/serialization/TGeoBoolNode$Companion {
public final class ru/mipt/npm/root/serialization/TGeoCombiTrans : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoCombiTrans$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[DLru/mipt/npm/root/serialization/TGeoRotation;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([DLru/mipt/npm/root/serialization/TGeoRotation;)V
public synthetic fun <init> ([DLru/mipt/npm/root/serialization/TGeoRotation;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFRotation ()Lru/mipt/npm/root/serialization/TGeoRotation;
public final fun getFTranslation ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoCombiTrans;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoCombiTrans$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoCombiTrans$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoCombiTrans;
@ -320,12 +180,15 @@ public final class ru/mipt/npm/root/serialization/TGeoCombiTrans$Companion {
public final class ru/mipt/npm/root/serialization/TGeoCompositeShape : ru/mipt/npm/root/serialization/TGeoBBox {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoCompositeShape$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DLru/mipt/npm/root/serialization/TGeoBoolNode;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoBoolNode;)V
public final fun getFNode ()Lru/mipt/npm/root/serialization/TGeoBoolNode;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoCompositeShape;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoCompositeShape$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoCompositeShape$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoCompositeShape;
@ -341,14 +204,17 @@ public final class ru/mipt/npm/root/serialization/TGeoCompositeShape$Companion {
public final class ru/mipt/npm/root/serialization/TGeoHMatrix : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoHMatrix$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[D[D[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([D[D[D)V
public final fun getFRotationMatrix ()[D
public final fun getFScale ()[D
public final fun getFTranslation ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoHMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoHMatrix$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoHMatrix$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoHMatrix;
@ -365,10 +231,13 @@ public final class ru/mipt/npm/root/serialization/TGeoHMatrix$Companion {
public final class ru/mipt/npm/root/serialization/TGeoIdentity : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoIdentity$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoIdentity;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoIdentity$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoIdentity$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoIdentity;
@ -384,13 +253,16 @@ public final class ru/mipt/npm/root/serialization/TGeoIdentity$Companion {
public final class ru/mipt/npm/root/serialization/TGeoIntersection : ru/mipt/npm/root/serialization/TGeoBoolNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoIntersection$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;)V
public fun getFLeft ()Lru/mipt/npm/root/serialization/TGeoShape;
public fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoIntersection;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoIntersection$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoIntersection$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoIntersection;
@ -407,14 +279,17 @@ public final class ru/mipt/npm/root/serialization/TGeoIntersection$Companion {
public final class ru/mipt/npm/root/serialization/TGeoManager : ru/mipt/npm/root/serialization/TNamed {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoManager$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TObjArray;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFMatrices ()Lru/mipt/npm/root/serialization/TObjArray;
public final fun getFNodes ()Lru/mipt/npm/root/serialization/TObjArray;
public final fun getFShapes ()Lru/mipt/npm/root/serialization/TObjArray;
public final fun getFVolumes ()Lru/mipt/npm/root/serialization/TObjArray;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoManager;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoManager$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoManager$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoManager;
@ -432,11 +307,12 @@ public class ru/mipt/npm/root/serialization/TGeoMaterial : ru/mipt/npm/root/seri
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMaterial$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoMaterial;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMaterial;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMaterial$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoMaterial$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoMaterial;
@ -453,7 +329,7 @@ public final class ru/mipt/npm/root/serialization/TGeoMaterial$Companion {
public abstract class ru/mipt/npm/root/serialization/TGeoMatrix : ru/mipt/npm/root/serialization/TNamed {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMatrix$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMatrix$Companion {
@ -462,14 +338,17 @@ public final class ru/mipt/npm/root/serialization/TGeoMatrix$Companion {
public final class ru/mipt/npm/root/serialization/TGeoMedium : ru/mipt/npm/root/serialization/TNamed {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMedium$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;ILru/mipt/npm/root/serialization/TGeoMaterial;[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (ILru/mipt/npm/root/serialization/TGeoMaterial;[D)V
public final fun getFId ()I
public final fun getFMaterial ()Lru/mipt/npm/root/serialization/TGeoMaterial;
public final fun getFParams ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMedium;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMedium$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoMedium$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoMedium;
@ -486,10 +365,13 @@ public final class ru/mipt/npm/root/serialization/TGeoMedium$Companion {
public final class ru/mipt/npm/root/serialization/TGeoMixture : ru/mipt/npm/root/serialization/TGeoMaterial {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoMixture$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoMixture;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoMixture$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoMixture$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoMixture;
@ -512,11 +394,12 @@ public class ru/mipt/npm/root/serialization/TGeoNode : ru/mipt/npm/root/serializ
public final fun getFNumber ()I
public final fun getFOverlaps ()[I
public final fun getFVolume ()Lru/mipt/npm/root/serialization/TGeoVolume;
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoNode;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoNode$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoNode$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoNode;
@ -533,11 +416,14 @@ public final class ru/mipt/npm/root/serialization/TGeoNode$Companion {
public final class ru/mipt/npm/root/serialization/TGeoNodeMatrix : ru/mipt/npm/root/serialization/TGeoNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoNodeMatrix$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoVolume;II[ILru/mipt/npm/root/serialization/TGeoMatrix;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFMatrix ()Lru/mipt/npm/root/serialization/TGeoMatrix;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoNodeMatrix;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoNodeMatrix$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoNodeMatrix$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoNodeMatrix;
@ -554,11 +440,14 @@ public final class ru/mipt/npm/root/serialization/TGeoNodeMatrix$Companion {
public final class ru/mipt/npm/root/serialization/TGeoNodeOffset : ru/mipt/npm/root/serialization/TGeoNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoNodeOffset$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoVolume;II[IDLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFOffset ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoNodeOffset;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoNodeOffset$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoNodeOffset$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoNodeOffset;
@ -582,11 +471,12 @@ public class ru/mipt/npm/root/serialization/TGeoPcon : ru/mipt/npm/root/serializ
public final fun getFRmax ()[D
public final fun getFRmin ()[D
public final fun getFZ ()[D
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoPcon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoPcon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoPcon$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoPcon$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoPcon;
@ -605,11 +495,12 @@ public class ru/mipt/npm/root/serialization/TGeoPgon : ru/mipt/npm/root/serializ
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DIDD[D[D[DILkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFNedges ()I
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoPgon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoPgon;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoPgon$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoPgon$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoPgon;
@ -625,12 +516,15 @@ public final class ru/mipt/npm/root/serialization/TGeoPgon$Companion {
public final class ru/mipt/npm/root/serialization/TGeoRotation : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoRotation$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([D)V
public final fun getFRotationMatrix ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoRotation;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoRotation$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoRotation$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoRotation;
@ -649,7 +543,7 @@ public abstract class ru/mipt/npm/root/serialization/TGeoShape : ru/mipt/npm/roo
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;ILkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFShapeBits-pVg5ArA ()I
public final fun getFShapeId ()I
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoShape$Companion {
@ -658,14 +552,17 @@ public final class ru/mipt/npm/root/serialization/TGeoShape$Companion {
public final class ru/mipt/npm/root/serialization/TGeoShapeAssembly : ru/mipt/npm/root/serialization/TGeoBBox {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoShapeAssembly$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DLru/mipt/npm/root/serialization/TGeoVolumeAssembly;ZLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;Z)V
public synthetic fun <init> (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFBBoxOK ()Z
public final fun getFVolume ()Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoShapeAssembly;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoShapeAssembly$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoShapeAssembly$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoShapeAssembly;
@ -686,13 +583,16 @@ public final class ru/mipt/npm/root/serialization/TGeoShapeRef : ru/mipt/npm/roo
public final class ru/mipt/npm/root/serialization/TGeoSubtraction : ru/mipt/npm/root/serialization/TGeoBoolNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoSubtraction$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;)V
public fun getFLeft ()Lru/mipt/npm/root/serialization/TGeoShape;
public fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoSubtraction;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoSubtraction$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoSubtraction$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoSubtraction;
@ -708,12 +608,15 @@ public final class ru/mipt/npm/root/serialization/TGeoSubtraction$Companion {
public final class ru/mipt/npm/root/serialization/TGeoTranslation : ru/mipt/npm/root/serialization/TGeoMatrix {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoTranslation$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> ([D)V
public final fun getFTranslation ()[D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoTranslation;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoTranslation$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoTranslation$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoTranslation;
@ -734,11 +637,12 @@ public class ru/mipt/npm/root/serialization/TGeoTube : ru/mipt/npm/root/serializ
public final fun getFDz ()D
public final fun getFRmax ()D
public final fun getFRmin ()D
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoTube;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoTube;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoTube$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoTube$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoTube;
@ -755,6 +659,7 @@ public final class ru/mipt/npm/root/serialization/TGeoTube$Companion {
public final class ru/mipt/npm/root/serialization/TGeoTubeSeg : ru/mipt/npm/root/serialization/TGeoTube {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoTubeSeg$Companion;
public fun <init> (DDDDDDDDD)V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DDDDDDDDDDDDDLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFC1 ()D
public final fun getFC2 ()D
public final fun getFCdfi ()D
@ -764,10 +669,12 @@ public final class ru/mipt/npm/root/serialization/TGeoTubeSeg : ru/mipt/npm/root
public final fun getFS1 ()D
public final fun getFS2 ()D
public final fun getFSm ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoTubeSeg;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoTubeSeg$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoTubeSeg$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoTubeSeg;
@ -783,13 +690,16 @@ public final class ru/mipt/npm/root/serialization/TGeoTubeSeg$Companion {
public final class ru/mipt/npm/root/serialization/TGeoUnion : ru/mipt/npm/root/serialization/TGeoBoolNode {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoUnion$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoMatrix;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoShape;)V
public fun getFLeft ()Lru/mipt/npm/root/serialization/TGeoShape;
public fun getFRight ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoUnion;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoUnion$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoUnion$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoUnion;
@ -819,11 +729,12 @@ public class ru/mipt/npm/root/serialization/TGeoVolume : ru/mipt/npm/root/serial
public final fun getFNumber ()I
public final fun getFRefCount ()I
public final fun getFShape ()Lru/mipt/npm/root/serialization/TGeoShape;
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolume;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolume;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoVolume$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoVolume$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoVolume;
@ -841,11 +752,12 @@ public class ru/mipt/npm/root/serialization/TGeoVolumeAssembly : ru/mipt/npm/roo
public static final field Companion Lru/mipt/npm/root/serialization/TGeoVolumeAssembly$Companion;
public fun <init> ()V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;ILjava/lang/Integer;Lkotlin/UInt;Ljava/lang/Integer;Ljava/lang/Integer;Lru/mipt/npm/root/serialization/TObjArray;Lru/mipt/npm/root/serialization/TGeoShape;Lru/mipt/npm/root/serialization/TGeoMedium;IIILkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoVolumeAssembly$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoVolumeAssembly$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoVolumeAssembly;
@ -872,6 +784,7 @@ public final class ru/mipt/npm/root/serialization/TGeoVolumeRef : ru/mipt/npm/ro
public final class ru/mipt/npm/root/serialization/TGeoXtru : ru/mipt/npm/root/serialization/TGeoBBox {
public static final field Companion Lru/mipt/npm/root/serialization/TGeoXtru$Companion;
public fun <init> (IID[D[D[D[D[D[D)V
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlin/UInt;IDDD[DIID[D[D[D[D[D[DLkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFNvert ()I
public final fun getFNz ()I
public final fun getFScale ()[D
@ -881,10 +794,12 @@ public final class ru/mipt/npm/root/serialization/TGeoXtru : ru/mipt/npm/root/se
public final fun getFY0 ()[D
public final fun getFZ ()[D
public final fun getFZcurrent ()D
public static final fun write$Self (Lru/mipt/npm/root/serialization/TGeoXtru;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TGeoXtru$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TGeoXtru$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TGeoXtru;
@ -900,12 +815,15 @@ public final class ru/mipt/npm/root/serialization/TGeoXtru$Companion {
public final class ru/mipt/npm/root/serialization/THashList : ru/mipt/npm/root/serialization/TObject {
public static final field Companion Lru/mipt/npm/root/serialization/THashList$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/util/List;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;)V
public final fun getArr ()Ljava/util/List;
public static final fun write$Self (Lru/mipt/npm/root/serialization/THashList;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/THashList$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/THashList$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/THashList;
@ -921,12 +839,15 @@ public final class ru/mipt/npm/root/serialization/THashList$Companion {
public final class ru/mipt/npm/root/serialization/TList : ru/mipt/npm/root/serialization/TObject {
public static final field Companion Lru/mipt/npm/root/serialization/TList$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/util/List;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;)V
public final fun getArr ()Ljava/util/List;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TList;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TList$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TList$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TList;
@ -946,11 +867,12 @@ public class ru/mipt/npm/root/serialization/TNamed : ru/mipt/npm/root/serializat
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFName ()Ljava/lang/String;
public final fun getFTitle ()Ljava/lang/String;
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TNamed;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TNamed;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TNamed$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lru/mipt/npm/root/serialization/TNamed$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/root/serialization/TNamed;
@ -966,11 +888,14 @@ public final class ru/mipt/npm/root/serialization/TNamed$Companion {
public final class ru/mipt/npm/root/serialization/TObjArray : ru/mipt/npm/root/serialization/TObject {
public static final field Companion Lru/mipt/npm/root/serialization/TObjArray$Companion;
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Ljava/util/List;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;)V
public final fun getArr ()Ljava/util/List;
public static final fun write$Self (Lru/mipt/npm/root/serialization/TObjArray;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlinx/serialization/KSerializer;)V
}
public final class ru/mipt/npm/root/serialization/TObjArray$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun <init> (Lkotlinx/serialization/KSerializer;)V
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
@ -992,7 +917,7 @@ public abstract class ru/mipt/npm/root/serialization/TObject {
public synthetic fun <init> (ILkotlin/UInt;Lkotlin/UInt;Lkotlinx/serialization/internal/SerializationConstructorMarker;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getFBits-pVg5ArA ()I
public final fun getFUniqueID-pVg5ArA ()I
public static final synthetic fun write$Self (Lru/mipt/npm/root/serialization/TObject;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
public static final fun write$Self (Lru/mipt/npm/root/serialization/TObject;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/root/serialization/TObject$Companion {

View File

@ -1,6 +1,9 @@
package ru.mipt.npm.root
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.double
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.set
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.parseAsName
import space.kscience.dataforge.names.plus
@ -362,7 +365,7 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
}
return if (group.children.isEmpty()) {
null
} else if (group.items.size == 1 && group.properties.own.isEmpty()) {
} else if (group.items.size == 1 && group.properties.own == null) {
group.items.values.first().apply { parent = null }
} else {
group

View File

@ -1,4 +0,0 @@
# Module compose-desktop-demo

View File

@ -1,17 +0,0 @@
public final class ComposableSingletons$MainKt {
public static final field INSTANCE LComposableSingletons$MainKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
public static field lambda-2 Lkotlin/jvm/functions/Function3;
public static field lambda-3 Lkotlin/jvm/functions/Function3;
public fun <init> ()V
public final fun getLambda-1$compose_desktop_demo ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-2$compose_desktop_demo ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-3$compose_desktop_demo ()Lkotlin/jvm/functions/Function3;
}
public final class MainKt {
public static final fun App (Landroidx/compose/runtime/Composer;I)V
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}

View File

@ -1,40 +0,0 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
}
kscience {
jvm()
useCoroutines()
commonMain{
implementation(projects.visionforgeSolid)
}
jvmMain {
implementation(projects.visionforgeComposeMultiplatform)
}
}
kotlin{
explicitApi = null
sourceSets{
commonMain{
dependencies {
implementation(compose.desktop.currentOs)
api(compose.preview)
}
}
}
}
compose{
desktop{
desktop {
application {
mainClass = "MainKt"
}
}
}
}

View File

@ -1,33 +0,0 @@
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import space.kscience.dataforge.meta.set
import space.kscience.visionforge.compose.PropertyEditor
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@Composable
@Preview
fun App(){
val options = remember {
Canvas3DOptions{
meta["custom.field"] = 32
}
}
PropertyEditor(
properties = options.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = true
)
}
fun main() = application {
Window(onCloseRequest = ::exitApplication) {
MaterialTheme {
App()
}
}
}

View File

@ -1,3 +1,21 @@
public final class space/kscience/visionforge/gdml/demo/GDMLDemoApp : tornadofx/App {
public fun <init> ()V
}
public final class space/kscience/visionforge/gdml/demo/GDMLView : tornadofx/View {
public static final field Companion Lspace/kscience/visionforge/gdml/demo/GDMLView$Companion;
public fun <init> ()V
public fun getRoot ()Ljavafx/scene/Parent;
}
public final class space/kscience/visionforge/gdml/demo/GDMLView$Companion {
}
public final class space/kscience/visionforge/gdml/demo/GdmlFxDemoAppKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/gdml/demo/ReadFileKt {
public static final fun readFile (Lspace/kscience/visionforge/VisionManager;Ljava/io/File;)Lspace/kscience/visionforge/Vision;
public static final fun readFile (Lspace/kscience/visionforge/VisionManager;Ljava/lang/String;)Lspace/kscience/visionforge/Vision;

View File

@ -1,23 +1,19 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
}
group = "demo"
kscience {
// jvm()
jvm()
js {
useCommonJs()
browser {
binaries.executable()
commonWebpackConfig {
cssSupport {
enabled = true
enabled.set(false)
}
scssSupport{
enabled = true
}
sourceMaps = true
}
}
}
@ -25,12 +21,14 @@ kscience {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeGdml)
}
// jvmMain {
//// implementation(project(":visionforge-fx"))
// implementation(spclibs.logback.classic)
// }
jvmMain {
// implementation(project(":visionforge-fx"))
implementation(spclibs.logback.classic)
}
jsMain {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
implementation(npm("react-file-drop", "3.0.6"))
}
}
@ -38,6 +36,30 @@ kotlin {
explicitApi = null
}
//kotlin {
//
// sourceSets {
// commonMain {
// dependencies {
// implementation(project(":visionforge-solid"))
// implementation(project(":visionforge-gdml"))
// }
// }
// jvmMain {
// dependencies {
//// implementation(project(":visionforge-fx"))
// implementation("ch.qos.logback:logback-classic:1.2.11")
// }
// }
// jsMain {
// dependencies {
// implementation(project(":ui:ring"))
// implementation(project(":visionforge-threejs"))
// implementation(npm("react-file-drop", "3.0.6"))
// }
// }
// }
//}
//val convertGdmlToJson by tasks.creating(JavaExec::class) {
// group = "application"

View File

@ -34,6 +34,6 @@ class GDMLVisionTest {
val child = cubes[Name.of("composite-000","segment-0")]
assertNotNull(child)
child.properties.setValue(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
assertEquals("red", child.properties[SolidMaterial.MATERIAL_COLOR_KEY].string)
assertEquals("red", child.properties.getMeta(SolidMaterial.MATERIAL_COLOR_KEY).string)
}
}

View File

@ -0,0 +1,50 @@
@file:JsModule("react-file-drop")
@file:JsNonModule
package drop
import org.w3c.dom.DragEvent
import org.w3c.files.FileList
import react.Component
import react.Props
import react.State
sealed external class DropEffects {
@JsName("copy")
object Copy : DropEffects
@JsName("move")
object Move : DropEffects
@JsName("link")
object Link : DropEffects
@JsName("none")
object None : DropEffects
}
external interface FileDropProps : Props {
var className: String?
var targetClassName: String?
var draggingOverFrameClassName: String?
var draggingOverTargetClassName: String?
// var frame?: Exclude<HTMLElementTagNameMap[keyof HTMLElementTagNameMap], HTMLElement> | HTMLDocument;
var onFrameDragEnter: ((event: DragEvent) -> Unit)?
var onFrameDragLeave: ((event: DragEvent) -> Unit)?
var onFrameDrop: ((event: DragEvent) -> Unit)?
// var onDragOver: ReactDragEventHandler<HTMLDivElement>?
// var onDragLeave: ReactDragEventHandler<HTMLDivElement>?
var onDrop: ((files: FileList?, event: dynamic) -> Unit)?//event:DragEvent<HTMLDivElement>)
var dropEffect: DropEffects?
}
external interface FileDropState : State {
var draggingOverFrame: Boolean
var draggingOverTarget: Boolean
}
external class FileDrop : Component<FileDropProps, FileDropState> {
override fun render(): dynamic
}

View File

@ -1,86 +0,0 @@
@file:OptIn(ExperimentalComposeWebApi::class)
package space.kscience.visionforge.gdml.demo
import androidx.compose.runtime.*
import bootstrap.Container
import bootstrap.Icon
import org.jetbrains.compose.web.ExperimentalComposeWebApi
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.name
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Input
import org.jetbrains.compose.web.dom.Text
import org.w3c.files.FileList
//https://codepen.io/zahedkamal87/pen/PobNNwE
@Composable
fun FileDrop(
title: String = "Drop files or Click here to select files to upload.",
onFileDrop: (FileList) -> Unit,
) {
var dragOver by remember { mutableStateOf(false) }
Container(attrs = {
id("dropzone")
style {
border(
width = 0.2.cssRem,
style = LineStyle.Dashed,
color = Color("#6583fe")
)
padding(2.cssRem)
borderRadius(0.25.cssRem)
backgroundColor(Color("#fff"))
textAlign("center")
fontSize(1.5.cssRem)
transitions {
all {
delay(0.25.s)
timingFunction(AnimationTimingFunction.EaseInOut)
properties("background-color")
}
}
cursor("pointer")
}
listOf("drag", "dragstart", "dragend", "dragenter").forEach {
addEventListener(it) { event ->
event.preventDefault()
event.stopPropagation()
}
}
onDragOver { event ->
event.preventDefault()
event.stopPropagation()
dragOver = true
}
onDragLeave { event ->
event.preventDefault()
event.stopPropagation()
dragOver = false
}
onDrop { event ->
event.preventDefault()
event.stopPropagation()
dragOver = false
event.dataTransfer?.files?.let {
onFileDrop(it)
}
}
}) {
Icon("cloud-upload"){ classes("dropzone-icon") }
Text(title)
Input(type = InputType.File, attrs = {
style {
display(DisplayStyle.None)
}
classes("dropzone-input")
name("files")
})
}
}
//
//dropzone.addEventListener("click", function(e) {
// dropzone_input.click();
//});

View File

@ -1,35 +1,46 @@
package space.kscience.visionforge.gdml.demo
import androidx.compose.runtime.*
import kotlinx.browser.window
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.P
import org.jetbrains.compose.web.dom.Text
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.css.*
import org.w3c.files.File
import org.w3c.files.FileReader
import org.w3c.files.get
import space.kscience.dataforge.context.Context
import react.Props
import react.dom.h2
import react.fc
import react.useState
import space.kscience.dataforge.names.Name
import space.kscience.gdml.Gdml
import space.kscience.gdml.decodeFromString
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.markLayers
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.compose.ThreeView
import space.kscience.visionforge.visionManager
import styled.css
import styled.styledDiv
external interface GDMLAppProps : Props {
var solids: Solids
var vision: Solid?
var selected: Name?
}
@Composable
fun GDMLApp(context: Context, initialVision: Solid?, selected: Name? = null) {
var vision: Solid? by remember { mutableStateOf(initialVision) }
@JsExport
val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
var deferredVision: Deferred<Solid?> by useState {
CompletableDeferred(props.vision)
}
fun readFileAsync(file: File) {
val visionManager = context.visionManager
fun readFileAsync(file: File): Deferred<Solid?> {
val deferred = CompletableDeferred<Solid?>()
FileReader().apply {
onload = {
val data = result as String
@ -38,7 +49,7 @@ fun GDMLApp(context: Context, initialVision: Solid?, selected: Name? = null) {
name.endsWith(".gdml") || name.endsWith(".xml") -> {
val gdml = Gdml.decodeFromString(data)
gdml.toVision().apply {
setAsRoot(visionManager)
setAsRoot(props.solids.visionManager)
console.info("Marking layers for file $name")
markLayers()
ambientLight {
@ -46,39 +57,44 @@ fun GDMLApp(context: Context, initialVision: Solid?, selected: Name? = null) {
}
}
}
name.endsWith(".json") -> visionManager.decodeFromString(data)
name.endsWith(".json") -> props.solids.visionManager.decodeFromString(data)
else -> {
window.alert("File extension is not recognized: $name")
error("File extension is not recognized: $name")
}
}
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
Unit
deferred.complete(parsedVision as? Solid ?: error("Parsed vision is not a solid"))
}
readAsText(file)
}
return deferred
}
Div({
style {
height(100.vh - 12.pt)
width(100.vw)
styledDiv {
css {
height = 100.vh - 12.pt
width = 100.vw
}
}) {
ThreeView(context, vision, selected) {
Tab("Load") {
P {
Text("Drag and drop .gdml or .json VisionForge files here")
child(ThreeCanvasWithControls) {
attrs {
this.solids = props.solids
this.builderOfSolid = deferredVision
this.selected = props.selected
tab("Load") {
h2 {
+"Drag and drop .gdml or .json VisionForge files here"
}
FileDrop("(drag file here)") { files ->
val file = files[0]
fileDrop("(drag file here)") { files ->
val file = files?.get(0)
if (file != null) {
readFileAsync(file)
}
}
deferredVision = readFileAsync(file)
}
}
}
}
}
}
}

View File

@ -1,57 +1,63 @@
package space.kscience.visionforge.gdml.demo
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Style
import org.jetbrains.compose.web.renderComposable
import kotlinx.css.*
import org.w3c.dom.Document
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.VisionForgeStyles
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication
import styled.injectGlobal
private class GDMLDemoApp : Application {
override fun start(document: Document, state: Map<String, Any>) {
val context = Context("gdml-demo"){
plugin(ThreePlugin)
}
override fun start(document: Document, state: Map<String, Any>) {
injectGlobal {
html{
height = 100.pct
}
body{
height = 100.pct
display = Display.flex
alignItems = Align.stretch
}
"#application"{
width = 100.pct
display = Display.flex
alignItems = Align.stretch
}
}
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
createRoot(element).render {
child(GDMLApp) {
val vision = GdmlShowCase.cubes().toVision().apply {
ambientLight {
color(Colors.white)
}
}
renderComposable(element) {
Style(VisionForgeStyles)
Style {
"html" {
height(100.percent)
}
"body" {
height(100.percent)
display(DisplayStyle.Flex)
alignItems(AlignItems.Stretch)
}
"#application" {
width(100.percent)
display(DisplayStyle.Flex)
alignItems(AlignItems.Stretch)
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
attrs {
this.solids = context.request(Solids)
this.vision = vision
}
}
GDMLApp(context, vision)
}
}
}

View File

@ -0,0 +1,30 @@
package space.kscience.visionforge.gdml.demo
import drop.FileDrop
import kotlinx.css.*
import org.w3c.files.FileList
import react.RBuilder
import styled.css
import styled.styledDiv
//TODO move styles to inline
fun RBuilder.fileDrop(title: String, action: (files: FileList?) -> Unit) {
styledDiv {
css {
border = Border(style = BorderStyle.dashed, width = 1.px, color = Color.orange)
flexGrow = 0.0
alignContent = Align.center
}
child(FileDrop::class) {
attrs {
onDrop = { files, _ ->
console.info("loaded $files")
action(files)
}
}
+title
}
}
}

3
demo/gdml/webpack.config.d/01.ring.js vendored Normal file
View File

@ -0,0 +1,3 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -1,6 +1,5 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
}
kscience {
@ -10,26 +9,27 @@ kscience {
kotlin {
explicitApi = null
js {
useCommonJs()
browser {
binaries.executable()
commonWebpackConfig {
cssSupport {
enabled = true
enabled.set(false)
}
scssSupport{
enabled = true
}
sourceMaps = true
}
}
}
}
kscience {
dependencies {
implementation(projects.visionforge.visionforgeGdml)
implementation(projects.visionforge.visionforgePlotly)
implementation(projects.visionforge.visionforgeMarkdown)
implementation(projects.visionforge.visionforgeThreejs)
}
jsMain {
implementation(projects.ui.ring)
}
}

View File

@ -1,20 +1,24 @@
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.renderComposable
import kotlinx.css.*
import org.w3c.dom.Document
import ringui.SmartTabs
import ringui.Tab
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.plotly.models.Trace
import space.kscience.plotly.scatter
import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.Tabs
import space.kscience.visionforge.html.VisionForgeStyles
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.JsVisionClient
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.ring.solid
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.solid.three.compose.ThreeView
import space.kscience.visionforge.startApplication
import styled.css
import styled.styledDiv
import kotlin.random.Random
fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number? = null, yErr: Number? = null) {
@ -26,32 +30,31 @@ fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number?
private class JsPlaygroundApp : Application {
val playgroundContext = Context {
plugin(ThreePlugin)
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
}
override fun start(document: Document, state: Map<String, Any>) {
// val solids = playgroundContext.request(Solids)
// val client = playgroundContext.request(JsVisionClient)
val playgroundContext = Context {
plugin(ThreeWithControlsPlugin)
plugin(JsVisionClient)
plugin(PlotlyPlugin)
}
val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page")
renderComposable(element) {
Style(VisionForgeStyles)
Div({
style {
padding(0.pt)
margin(0.pt)
height(100.vh)
width(100.vw)
createRoot(element).render {
styledDiv {
css {
padding = Padding(0.pt)
margin = Margin(0.pt)
height = 100.vh
width = 100.vw
}
}) {
Tabs("gravity") {
SmartTabs("gravity") {
Tab("gravity") {
GravityDemo(playgroundContext)
GravityDemo {
attrs {
this.solids = playgroundContext.request(Solids)
}
}
}
// Tab("D0") {
@ -63,31 +66,38 @@ private class JsPlaygroundApp : Application {
// }
// }
Tab("spheres") {
Div({
style {
height(100.vh - 50.pt)
styledDiv {
css {
height = 100.vh - 50.pt
}
}) {
ThreeView(playgroundContext, SolidGroup {
child(ThreeCanvasWithControls) {
val random = Random(112233)
attrs {
solids = playgroundContext.request(Solids)
solid {
ambientLight {
color(Colors.white)
}
repeat(100) {
sphere(5, name = "sphere[$it]") {
x = Random.nextDouble(-300.0, 300.0)
y = Random.nextDouble(-300.0, 300.0)
z = Random.nextDouble(-300.0, 300.0)
x = random.nextDouble(-300.0, 300.0)
y = random.nextDouble(-300.0, 300.0)
z = random.nextDouble(-300.0, 300.0)
material {
color(Random.nextInt())
color(random.nextInt())
}
detail = 16
}
}
})
}
}
}
}
}
Tab("plotly") {
Plot(playgroundContext) {
Plotly {
attrs {
plot = space.kscience.plotly.Plotly.plot {
scatter {
x(1, 2, 3)
y(5, 8, 7)
@ -98,7 +108,8 @@ private class JsPlaygroundApp : Application {
}
}
}
}
}
}
public fun main() {

View File

@ -1,75 +1,46 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import bootstrap.Column
import bootstrap.Row
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLDivElement
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta
import space.kscience.plotly.Plot
import kotlinx.coroutines.launch
import kotlinx.css.*
import react.Props
import react.fc
import space.kscience.plotly.layout
import space.kscience.plotly.models.Trace
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.Vision
import space.kscience.visionforge.html.zIndex
import space.kscience.visionforge.markup.VisionOfMarkup
import space.kscience.visionforge.plotly.asVision
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.solid
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.three.compose.ThreeView
import styled.css
import styled.styledDiv
import kotlin.math.sqrt
@Composable
fun Plot(
context: Context,
meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null,
block: Plot.() -> Unit,
) = Vision(
context = context,
attrs = attrs,
meta = meta,
vision = Plot().apply(block).asVision()
)
external interface DemoProps : Props {
var solids: Solids
}
@Composable
fun Markup(
context: Context,
markup: VisionOfMarkup,
meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null,
) = Vision(
context = context,
attrs = attrs,
meta = meta,
vision = markup
)
private val h = 100.0
@Composable
fun GravityDemo(context: Context) {
val velocityTrace = remember {
Trace {
val GravityDemo = fc<DemoProps> { props ->
val velocityTrace = Trace {
name = "velocity"
}
}
val energyTrace = remember {
Trace {
val energyTrace = Trace {
name = "energy"
}
val markup = VisionOfMarkup()
styledDiv {
css {
height = 100.vh - 50.pt
}
val markup = remember { VisionOfMarkup() }
val solid = remember {
SolidGroup {
styledDiv {
css {
height = 50.vh
}
child(ThreeCanvasWithControls) {
attrs {
solids = props.solids
solid {
pointLight(200, 200, 200, name = "light"){
color(Colors.white)
}
@ -78,18 +49,9 @@ fun GravityDemo(context: Context) {
sphere(5.0, "ball") {
detail = 16
color("red")
val h = 100.0
y = h
box(200, 5, 200, name = "floor") {
y = -2.5
}
}
}
}
LaunchedEffect(solid) {
val ball = solid["ball"]!!
solids.context.launch {
val g = 10.0
val dt = 0.1
var time = 0.0
@ -98,13 +60,13 @@ fun GravityDemo(context: Context) {
delay(20)
time += dt
velocity -= g * dt
val energy = g * ball.y.toDouble() + velocity * velocity / 2
ball.y = ball.y.toDouble() + velocity * dt
val energy = g * y.toDouble() + velocity * velocity / 2
y = y.toDouble() + velocity * dt
velocityTrace.appendXYLatest(time, ball.y)
velocityTrace.appendXYLatest(time, y)
energyTrace.appendXYLatest(time, energy)
if (ball.y.toDouble() <= 2.5) {
if (y.toDouble() <= 2.5) {
//conservation of energy
velocity = sqrt(2 * g * h)
}
@ -118,46 +80,31 @@ fun GravityDemo(context: Context) {
""".trimIndent()
}
}
}
Div({
style {
height(100.vh - 50.pt)
box(200, 5, 200, name = "floor") {
y = -2.5
}
}) {
Div({
style {
height(50.vh)
}
}) {
ThreeView(context, solid)
}
Row(attrs = {
style {
alignContent(AlignContent.Stretch)
alignItems(AlignItems.Stretch)
height(50.vh - 50.pt)
}
}) {
Column {
Plot(context) {
}
flexRow {
css {
alignContent = Align.stretch
alignItems = Align.stretch
height = 50.vh - 50.pt
}
plotly {
traces(velocityTrace, energyTrace)
layout {
xaxis.title = "time"
}
}
}
Column {
Markup(context, markup, attrs = {
style {
width(100.percent)
height(100.percent)
border(2.pt, LineStyle.Solid, Color.blue)
paddingLeft(8.pt)
backgroundColor(Color.white)
flex(1)
zIndex(10000)
}
})
Markup {
attrs {
this.markup = markup
}
}
}
}

View File

@ -0,0 +1,55 @@
import kotlinx.css.*
import kotlinx.dom.clear
import kotlinx.html.dom.append
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
import react.Props
import react.fc
import react.useEffect
import react.useRef
import space.kscience.visionforge.markup.VisionOfMarkup
import space.kscience.visionforge.markup.markdown
import space.kscience.visionforge.useProperty
import styled.css
import styled.styledDiv
external interface MarkupProps : Props {
var markup: VisionOfMarkup?
}
val Markup = fc<MarkupProps>("Markup") { props ->
val elementRef = useRef<Element>(null)
useEffect(props.markup, elementRef) {
val element = elementRef.current as? HTMLElement ?: error("Markup element not found")
props.markup?.let { vision ->
val flavour = when (vision.format) {
VisionOfMarkup.COMMONMARK_FORMAT -> CommonMarkFlavourDescriptor()
VisionOfMarkup.GFM_FORMAT -> GFMFlavourDescriptor()
//TODO add new formats via plugins
else -> error("Format ${vision.format} not recognized")
}
vision.useProperty(VisionOfMarkup::content) { content: String? ->
element.clear()
element.append {
markdown(flavour) { content ?: "" }
}
}
}
}
styledDiv {
css {
width = 100.pct
height = 100.pct
border= Border(2.pt, BorderStyle.solid, Color.blue)
padding = Padding(left = 8.pt)
backgroundColor = Color.white
flex = Flex(1.0)
zIndex = 10000
}
ref = elementRef
}
}

View File

@ -0,0 +1,43 @@
import kotlinx.css.*
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
import react.*
import space.kscience.plotly.Plot
import space.kscience.plotly.PlotlyConfig
import space.kscience.plotly.plot
import styled.css
import styled.styledDiv
external interface PlotlyProps : Props {
var plot: Plot?
}
val Plotly = fc<PlotlyProps>("Plotly") { props ->
val elementRef = useRef<Element>(null)
useEffect(props.plot, elementRef) {
val element = elementRef.current as? HTMLElement ?: error("Plotly element not found")
props.plot?.let {
element.plot(PlotlyConfig {
responsive = true
}, it)
}
}
styledDiv {
css {
width = 100.pct
height = 100.pct
border = Border(2.pt, BorderStyle.solid, Color.blue)
flex = Flex(1.0)
}
ref = elementRef
}
}
fun RBuilder.plotly(plotbuilder: Plot.() -> Unit) = Plotly {
attrs {
this.plot = Plot().apply(plotbuilder)
}
}

View File

@ -0,0 +1,3 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -1,6 +1,6 @@
public final class ru/mipt/npm/muon/monitor/Event {
public static final field $stable I
public static final field Companion Lru/mipt/npm/muon/monitor/Event$Companion;
public synthetic fun <init> (IILjava/util/List;Ljava/util/Collection;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V
public fun <init> (ILjava/util/List;Ljava/util/Collection;)V
public final fun component1 ()I
public final fun component2 ()Ljava/util/List;
@ -13,11 +13,12 @@ public final class ru/mipt/npm/muon/monitor/Event {
public final fun getTrack ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public static final fun write$Self (Lru/mipt/npm/muon/monitor/Event;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}
public final class ru/mipt/npm/muon/monitor/Event$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field $stable I
public static final field INSTANCE Lru/mipt/npm/muon/monitor/Event$$serializer;
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lru/mipt/npm/muon/monitor/Event;
@ -32,7 +33,6 @@ public final class ru/mipt/npm/muon/monitor/Event$Companion {
}
public final class ru/mipt/npm/muon/monitor/Model {
public static final field $stable I
public fun <init> (Lspace/kscience/visionforge/VisionManager;)V
public final fun displayEvent (Lru/mipt/npm/muon/monitor/Event;)V
public final fun encodeToString ()Ljava/lang/String;
@ -40,10 +40,10 @@ public final class ru/mipt/npm/muon/monitor/Model {
public final fun getRoot ()Lspace/kscience/visionforge/solid/SolidGroup;
public final fun getTracks ()Lspace/kscience/visionforge/solid/SolidGroup;
public final fun reset ()V
public final fun setTracks (Lspace/kscience/visionforge/solid/SolidGroup;)V
}
public final class ru/mipt/npm/muon/monitor/Monitor {
public static final field $stable I
public static final field CENTRAL_LAYER_Z F
public static final field GEOMETRY_TOLERANCE D
public static final field INSTANCE Lru/mipt/npm/muon/monitor/Monitor;
@ -61,10 +61,9 @@ public final class ru/mipt/npm/muon/monitor/ReadResourceKt {
}
public final class ru/mipt/npm/muon/monitor/SC1 {
public static final field $stable I
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Float32Vector3D;FFF)V
public synthetic fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Float32Vector3D;FFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Float32Vector3D;
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Point3D;FFF)V
public synthetic fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Point3D;FFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Point3D;
public final fun getName ()Ljava/lang/String;
public final fun getXSize ()F
public final fun getYSize ()F
@ -72,9 +71,8 @@ public final class ru/mipt/npm/muon/monitor/SC1 {
}
public final class ru/mipt/npm/muon/monitor/SC16 {
public static final field $stable I
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Float32Vector3D;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Float32Vector3D;
public fun <init> (Ljava/lang/String;Lspace/kscience/visionforge/solid/Point3D;)V
public final fun getCenter ()Lspace/kscience/visionforge/solid/Point3D;
public final fun getName ()Ljava/lang/String;
public final fun getPixels ()Ljava/util/Collection;
}
@ -82,12 +80,11 @@ public final class ru/mipt/npm/muon/monitor/SC16 {
public final class ru/mipt/npm/muon/monitor/server/MMServerKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
public static final fun module (Lio/ktor/server/application/Application;Lspace/kscience/dataforge/context/Context;)V
public static synthetic fun module$default (Lio/ktor/server/application/Application;Lspace/kscience/dataforge/context/Context;ILjava/lang/Object;)V
public static final fun module (Lio/ktor/application/Application;Lspace/kscience/dataforge/context/Context;)V
public static synthetic fun module$default (Lio/ktor/application/Application;Lspace/kscience/dataforge/context/Context;ILjava/lang/Object;)V
}
public final class ru/mipt/npm/muon/monitor/sim/Cos2TrackGenerator : ru/mipt/npm/muon/monitor/sim/TrackGenerator {
public static final field $stable I
public fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DFF)V
public synthetic fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun generate ()Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
@ -98,7 +95,6 @@ public final class ru/mipt/npm/muon/monitor/sim/Cos2TrackGenerator : ru/mipt/npm
}
public final class ru/mipt/npm/muon/monitor/sim/FixedAngleGenerator : ru/mipt/npm/muon/monitor/sim/TrackGenerator {
public static final field $stable I
public fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DDFF)V
public synthetic fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;DDFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun generate ()Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
@ -116,8 +112,8 @@ public final class ru/mipt/npm/muon/monitor/sim/LineKt {
public static final fun getY (Lorg/apache/commons/math3/geometry/euclidean/threed/Line;)D
public static final fun makeTrack (DDDD)Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
public static final fun makeTrack (Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;)Lorg/apache/commons/math3/geometry/euclidean/threed/Line;
public static final fun toKMathVector (Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;)Lspace/kscience/visionforge/solid/Float32Vector3D;
public static final fun toKMathVectors (Lorg/apache/commons/math3/geometry/euclidean/threed/Line;)Ljava/util/List;
public static final fun toPoint (Lorg/apache/commons/math3/geometry/euclidean/threed/Vector3D;)Lspace/kscience/visionforge/solid/Point3D;
public static final fun toPoints (Lorg/apache/commons/math3/geometry/euclidean/threed/Line;)Ljava/util/List;
}
public final class ru/mipt/npm/muon/monitor/sim/MonitorKt {
@ -142,7 +138,6 @@ public abstract interface class ru/mipt/npm/muon/monitor/sim/TrackGenerator {
}
public final class ru/mipt/npm/muon/monitor/sim/UniformTrackGenerator : ru/mipt/npm/muon/monitor/sim/TrackGenerator {
public static final field $stable I
public fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;FF)V
public synthetic fun <init> (Lorg/apache/commons/math3/random/RandomGenerator;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun generate ()Lorg/apache/commons/math3/geometry/euclidean/threed/Line;

View File

@ -1,54 +1,58 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
// alias(spclibs.plugins.ktor)
application
}
group = "ru.mipt.npm"
val ktorVersion: String = spclibs.versions.ktor.get()
kscience {
fullStack(
"muon-monitor.js",
jvmConfig = {withJava()},
browserConfig = {
commonWebpackConfig {
cssSupport {
enabled = true
}
scssSupport {
enabled = true
}
}
}
)
useCoroutines()
useSerialization()
useKtor()
fullStack(
"muon-monitor.js",
jvmConfig = { withJava() },
jsConfig = { useCommonJs() }
) {
commonWebpackConfig {
cssSupport {
enabled.set(false)
}
}
}
commonMain {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeComposeHtml)
}
jvmMain {
implementation("org.apache.commons:commons-math3:3.6.1")
implementation("io.ktor:ktor-server-cio")
implementation("io.ktor:ktor-server-content-negotiation")
implementation("io.ktor:ktor-serialization-kotlinx-json")
implementation(spclibs.logback.classic)
implementation("io.ktor:ktor-server-cio:${ktorVersion}")
implementation("io.ktor:ktor-server-content-negotiation:${ktorVersion}")
implementation("io.ktor:ktor-serialization-kotlinx-json:${ktorVersion}")
implementation("ch.qos.logback:logback-classic:1.2.11")
}
jsMain {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
}
}
kotlin {
explicitApi = null
}
kotlin.explicitApi = null
application {
mainClass.set("ru.mipt.npm.muon.monitor.MMServerKt")
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
}
//distributions {
// main {
// contents {
// from("$buildDir/libs") {
// rename("${rootProject.name}-jvm", rootProject.name)
// into("lib")
// }
// }
// }
//}

View File

@ -71,7 +71,7 @@ class Model(val manager: VisionManager) {
fun reset() {
map.values.forEach {
it.properties[SolidMaterial.MATERIAL_COLOR_KEY] = null
it.properties.setMeta(SolidMaterial.MATERIAL_COLOR_KEY, null)
}
tracks.children.clear()
}

View File

@ -1,47 +1,61 @@
package ru.mipt.npm.muon.monitor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import bootstrap.Button
import bootstrap.ButtonGroup
import bootstrap.Layout.Width.Full
import kotlinx.browser.window
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.await
import kotlinx.coroutines.launch
import kotlinx.css.*
import kotlinx.html.js.onClickFunction
import kotlinx.serialization.json.Json
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.P
import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text
import org.w3c.fetch.RequestInit
import space.kscience.dataforge.context.Context
import react.Props
import react.dom.attrs
import react.dom.button
import react.dom.p
import react.fc
import react.useMemo
import react.useState
import space.kscience.dataforge.meta.invoke
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Colors
import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.edges
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.compose.ThreeView
import styled.css
import styled.styledDiv
import styled.styledSpan
import kotlin.math.PI
@Composable
fun MMApp(context: Context, model: Model, selected: Name? = null) {
external interface MMAppProps : Props {
var model: Model
var solids: Solids
var selected: Name?
}
val mmOptions = remember {
@OptIn(DelicateCoroutinesApi::class)
@JsExport
val MMApp = fc<MMAppProps>("Muon monitor") { props ->
val mmOptions = useMemo {
Canvas3DOptions {
camera {
distance = 2100.0
latitude = PI / 6
azimuth = PI + PI / 6
}
}
}
val root = remember(model) {
model.root.apply {
val root = useMemo(props.model) {
props.model.root.apply {
edges()
ambientLight{
color(Colors.white)
@ -49,26 +63,26 @@ fun MMApp(context: Context, model: Model, selected: Name? = null) {
}
}
val events = remember { mutableStateListOf<Event>() }
var events: Set<Event> by useState(emptySet())
Div(
attrs = {
classes("container-fluid")
style {
height(100.vh - 12.pt)
styledDiv {
css {
height = 100.vh - 12.pt
}
}
) {
ThreeView(
context,
solid = root,
initialSelected = selected,
options = mmOptions,
sidebarTabs = {
Tab("Events") {
ButtonGroup({ Layout.width = Full }) {
Button("Next") {
context.launch {
child(ThreeCanvasWithControls) {
attrs {
this.solids = props.solids
this.builderOfSolid = CompletableDeferred(root)
this.selected = props.selected
this.options = mmOptions
tab("Events") {
flexColumn {
flexRow {
button {
+"Next"
attrs {
onClickFunction = {
solids.context.launch {
val event = window.fetch(
"http://localhost:8080/event",
RequestInit("GET")
@ -81,33 +95,187 @@ fun MMApp(context: Context, model: Model, selected: Name? = null) {
}.then { body ->
Json.decodeFromString(Event.serializer(), body)
}.await()
events.add(event)
model.displayEvent(event)
events = events + event
props.model.displayEvent(event)
}
}
}
}
button {
+"Clear"
attrs {
onClickFunction = {
events = emptySet()
props.model.reset()
}
}
}
}
}
events.forEach { event ->
p {
styledSpan {
+event.id.toString()
}
+" : "
styledSpan {
css {
color = Color.blue
}
+event.hits.toString()
}
}
}
Button("Clear", color = bootstrap.Color.Secondary) {
events.clear()
model.reset()
}
}
events.forEach { event ->
P {
Span {
Text(event.id.toString())
}
Text(" : ")
Span({
style {
color(Color.blue)
}
}) {
Text(event.hits.toString())
}
}
}
}
}
)
}
// var selected by useState { props.selected }
//
// val onSelect: (Name?) -> Unit = {
// selected = it
// }
//
//
// gridRow {
// flexColumn {
// css {
// +"col-lg-3"
// +"order-lg-1"
// +"order-2"
// padding(0.px)
// overflowY = Overflow.auto
// height = 100.vh
// }
// //tree
// card("Object tree") {
// css {
// flex(1.0, 1.0, FlexBasis.auto)
// }
// visionTree(root, selected, onSelect)
// }
// }
// flexColumn {
// css {
// +"col-lg-6"
// +"order-lg-2"
// +"order-1"
// height = 100.vh
// }
// h1("mx-auto page-header") {
// +"Muon monitor demo"
// }
// //canvas
//
// child(ThreeCanvasComponent) {
// attrs {
// this.context = props.context
// this.solid = root
// this.selected = selected
// this.options = mmOptions
// }
// }
// }
// flexColumn {
// css {
// +"col-lg-3"
// +"order-3"
// padding(0.px)
// height = 100.vh
// }
// styledDiv {
// css {
// flex(0.0, 1.0, FlexBasis.zero)
// }
// //settings
// card("Canvas configuration") {
// canvasControls(mmOptions, root)
// }
//
// card("Events") {
// button {
// +"Next"
// attrs {
// onClickFunction = {
// GlobalScope.launch {
// val event = props.connection.get<Event>("http://localhost:8080/event")
// props.model.displayEvent(event)
// }
// }
// }
// }
// button {
// +"Clear"
// attrs {
// onClickFunction = {
// props.model.reset()
// }
// }
// }
// }
// }
// styledDiv {
// css {
// padding(0.px)
// }
// nav {
// attrs {
// attributes["aria-label"] = "breadcrumb"
// }
// ol("breadcrumb") {
// li("breadcrumb-item") {
// button(classes = "btn btn-link p-0") {
// +"World"
// attrs {
// onClickFunction = {
// selected = Name.EMPTY
// }
// }
// }
// }
// if (selected != null) {
// val tokens = ArrayList<NameToken>(selected?.length ?: 1)
// selected?.tokens?.forEach { token ->
// tokens.add(token)
// val fullName = Name(tokens.toList())
// li("breadcrumb-item") {
// button(classes = "btn btn-link p-0") {
// +token.toString()
// attrs {
// onClickFunction = {
// console.log("Selected = $fullName")
// selected = fullName
// }
// }
// }
// }
// }
// }
// }
// }
// }
// styledDiv {
// css {
// overflowY = Overflow.auto
// }
// //properties
// card("Properties") {
// selected.let { selected ->
// val selectedObject: Vision? = when {
// selected == null -> null
// selected.isEmpty() -> root
// else -> root[selected]
// }
// if (selectedObject != null) {
// visionPropertyEditor(selectedObject, key = selected)
// }
// }
// }
// }
// }
//
// }
}

View File

@ -1,15 +1,15 @@
package ru.mipt.npm.muon.monitor
import org.jetbrains.compose.web.css.Style
import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.visionforge.Application
import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.VisionForgeStyles
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication
private class MMDemoApp : Application {
@ -23,9 +23,14 @@ private class MMDemoApp : Application {
val model = Model(visionManager)
renderComposable("app") {
Style(VisionForgeStyles)
MMApp(context, model)
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
createRoot(element).render {
child(MMApp) {
attrs {
this.model = model
this.solids = context.request(Solids)
}
}
}
}
}

View File

@ -1,4 +1,4 @@
package ru.mipt.npm.muon.monitor
package ru.mipt.npm.muon.monitor.server
import io.ktor.http.ContentType
@ -17,6 +17,7 @@ import io.ktor.server.response.respondText
import io.ktor.server.routing.Routing
import io.ktor.server.routing.get
import org.apache.commons.math3.random.JDKRandomGenerator
import ru.mipt.npm.muon.monitor.Model
import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
import ru.mipt.npm.muon.monitor.sim.simulateOne
import space.kscience.dataforge.context.Context

View File

@ -0,0 +1,3 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -3,36 +3,6 @@ public final class space/kscience/visionforge/examples/AllThingsDemoKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/AntennaKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/AxesKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/BmnDemoKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ControlVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/DynamicPlotlyVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ExtrudedKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/FormServerKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
@ -58,11 +28,6 @@ public final class space/kscience/visionforge/examples/GenerateSchemaKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/MarkdownVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/PlotlyVisionKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
@ -73,28 +38,21 @@ public final class space/kscience/visionforge/examples/RandomSpheresKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ServerExtensionsKt {
public static final fun makeVisionFile (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLspace/kscience/visionforge/html/HtmlVisionFragment;)V
public static synthetic fun makeVisionFile$default (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
public static final fun serve (Ljava/lang/String;ZLspace/kscience/visionforge/html/HtmlVisionFragment;)V
public static synthetic fun serve$default (Ljava/lang/String;ZLspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
}
public final class space/kscience/visionforge/examples/ShapesKt {
public final class space/kscience/visionforge/examples/RootParserKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/ServerExtensionsKt {
public static final fun makeVisionFile (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLkotlin/jvm/functions/Function1;)V
public static synthetic fun makeVisionFile$default (Ljava/nio/file/Path;Ljava/lang/String;Lspace/kscience/visionforge/html/ResourceLocation;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}
public final class space/kscience/visionforge/examples/SimpleCubeKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/SurfaceKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/examples/TablesKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V

View File

@ -12,27 +12,31 @@ repositories {
}
kotlin {
jvmToolchain(11)
js(IR) {
useCommonJs()
browser {
webpackTask {
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
mainOutputFileName.set("js/visionforge-playground.js")
}
commonWebpackConfig {
sourceMaps = true
cssSupport{
enabled.set(false)
}
}
}
binaries.executable()
}
jvm {
// withJava()
compilerOptions {
freeCompilerArgs.addAll("-Xjvm-default=all", "-Xopt-in=kotlin.RequiresOptIn", "-Xlambdas=indy", "-Xcontext-receivers")
compilations.all {
kotlinOptions {
jvmTarget = "11"
freeCompilerArgs =
freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" + "-Xcontext-receivers"
}
}
testRuns["test"].executionTask.configure {
useJUnitPlatform()
@ -53,6 +57,7 @@ kotlin {
val jsMain by getting {
dependencies {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
compileOnly(npm("webpack-bundle-analyzer","4.5.0"))
}

View File

@ -54,6 +54,9 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"jupyter": {
"outputs_hidden": false
},
"tags": []
},
"outputs": [],
@ -80,6 +83,9 @@
"language": "kotlin",
"name": "kotlin"
},
"ktnbPluginMetadata": {
"isAddProjectLibrariesToClasspath": false
},
"language_info": {
"codemirror_mode": "text/x-kotlin",
"file_extension": ".kt",
@ -88,9 +94,6 @@
"nbconvert_exporter": "",
"pygments_lexer": "kotlin",
"version": "1.8.20"
},
"ktnbPluginMetadata": {
"projectLibraries": []
}
},
"nbformat": 4,

View File

@ -1,45 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"USE(JupyterCommonIntegration())"
]
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [],
"metadata": {
"collapsed": false
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.9.0",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
},
"ktnbPluginMetadata": {
"projectDependencies": true
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -25,7 +25,10 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
@ -81,7 +84,7 @@
"version": "1.8.0-dev-3517"
},
"ktnbPluginMetadata": {
"projectLibraries": []
"isAddProjectLibrariesToClasspath": false
}
},
"nbformat": 4,

View File

@ -1,14 +1,14 @@
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.html.runVisionClient
import space.kscience.visionforge.jupyter.VFNotebookClient
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.runVisionClient
import space.kscience.visionforge.tables.TableVisionJsPlugin
@DFExperimental
fun main() = runVisionClient {
plugin(ThreePlugin)
plugin(ThreeWithControlsPlugin)
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
plugin(TableVisionJsPlugin)

View File

@ -2,6 +2,7 @@ package space.kscience.visionforge.examples
import kotlinx.html.h2
import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.invoke
import space.kscience.plotly.layout
import space.kscience.plotly.models.ScatterMode
import space.kscience.plotly.models.TextPosition
@ -10,9 +11,9 @@ import space.kscience.tables.ColumnHeader
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.markup.markdown
import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.solid.axes
import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.z
import space.kscience.visionforge.tables.columnTable
import kotlin.io.path.Path
@ -33,8 +34,14 @@ fun main() = makeVisionFile(
h2 { +"3D visualization with Three-js" }
vision("3D") {
solid {
axes(200)
solid(
Canvas3DOptions {
axes {
size = 200.0
visible = true
}
}
) {
box(100, 100, 100, name = "aBox") {
z = 50.0
}

View File

@ -1,71 +0,0 @@
package space.kscience.visionforge.examples
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.html.h2
import kotlinx.html.p
import space.kscience.visionforge.VisionControlEvent
import space.kscience.visionforge.html.*
import space.kscience.visionforge.onSubmit
import kotlin.time.Duration.Companion.seconds
fun main() = serve {
val events = ArrayDeque<VisionControlEvent>(10)
val html = VisionOfPlainHtml()
fun pushEvent(event: VisionControlEvent) {
events.addFirst(event)
if (events.size >= 10) {
events.removeLast()
}
html.content {
events.forEach { event ->
p {
text(event.toString())
}
}
}
}
h2 { +"Control elements" }
vision {
htmlCheckBox {
checked = true
onValueChange(context) {
pushEvent(this)
}
}
}
vision {
htmlRangeField(1, 10) {
numberValue = 4
onValueChange(context) {
pushEvent(this)
}
context.launch {
while (isActive) {
delay(1.seconds)
numberValue = ((numberValue?.toInt() ?: 0) + 1) % 10
}
}
}
}
vision {
button("Click me") {
onSubmit(context) {
pushEvent(this)
}
}
}
vision(html)
}

View File

@ -1,112 +0,0 @@
package space.kscience.visionforge.examples
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.routing
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.html.a
import kotlinx.html.h1
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.request
import space.kscience.plotly.layout
import space.kscience.plotly.models.Trace
import space.kscience.plotly.models.invoke
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
fun main() {
val plotlyPlugin = Global.request(PlotlyPlugin)
val visionManager = plotlyPlugin.visionManager
val server = embeddedServer(CIO) {
routing {
staticResources("/", null)
}
val freq = 1.0 / 1000
val oscillationFreq = 1.0 / 10000
val x = (0..100).map { it.toDouble() / 100.0 }
val sinY = x.map { sin(2.0 * PI * it) }
val cosY = x.map { cos(2.0 * PI * it) }
val sinTrace = Trace(x, sinY) { name = "sin" }
val cosTrace = Trace(x, cosY) { name = "cos" }
visionPage(
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
) {
h1 { +"This is the plot page" }
a("/other") { +"The other page" }
vision {
plotly {
traces(sinTrace, cosTrace)
layout {
title = "Other dynamic plot"
xaxis.title = "x axis name"
yaxis.title = "y axis name"
}
}
}
}
visionPage(
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
route = "other"
) {
h1 { +"This is the other plot page" }
a("/") { +"Back to the main page" }
vision {
plotly {
traces(sinTrace)
layout {
title = "Dynamic plot"
xaxis.title = "x axis name"
yaxis.title = "y axis name"
}
}
}
}
//Start pushing updates
launch {
var time: Long = 0
while (isActive) {
delay(10)
time += 10
sinTrace.y.numbers = x.map { sin(2.0 * PI * (it + time.toDouble() * freq)) }
val cosAmp = cos(2.0 * PI * oscillationFreq * time)
cosTrace.y.numbers = x.map { cos(2.0 * PI * (it + time.toDouble() * freq)) * cosAmp }
}
}
}.start(false)
server.openInBrowser()
while (readlnOrNull() != "exit") {
}
server.close()
}

View File

@ -10,7 +10,7 @@ import space.kscience.dataforge.context.request
import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.html.VisionOfHtmlForm
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.html.visionOfForm
import space.kscience.visionforge.html.bindForm
import space.kscience.visionforge.onPropertyChange
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
@ -36,7 +36,7 @@ fun main() {
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
) {
visionOfForm(form) {
bindForm(form) {
label {
htmlFor = "fname"
+"First name:"
@ -67,15 +67,15 @@ fun main() {
value = "Submit"
}
}
vision(form)
println(form.values)
vision(form)
}
}.start(false)
server.openInBrowser()
while (readlnOrNull() != "exit") {
while (readln() != "exit") {
}

View File

@ -1,19 +0,0 @@
package space.kscience.visionforge.examples
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.markup.markdown
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision {
markdown{
content = """
# h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
""".trimIndent()
}
}
}

View File

@ -0,0 +1,23 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
const path = require('path');
config.module.rules.push(...ringConfig.module.rules)
config.module.rules.push(
{
test: /\.css$/,
exclude: [
path.resolve(__dirname, "../../node_modules/@jetbrains/ring-ui")
],
use: [
{
loader: 'style-loader',
options: {}
},
{
loader: 'css-loader',
options: {}
}
]
}
)

View File

@ -3,8 +3,3 @@ public final class ru/mipt/npm/sat/SatServerKt {
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class ru/mipt/npm/sat/StaticKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}

View File

@ -1,9 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.ktor)
id("space.kscience.gradle.jvm")
application
}
@ -12,10 +8,8 @@ kscience {
// useSerialization {
// json()
// }
jvm{
withJava()
}
jvmMain{
useKtor()
dependencies{
implementation("io.ktor:ktor-server-cio")
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
implementation(spclibs.logback.classic)
@ -24,8 +18,6 @@ kscience {
group = "center.sciprog"
kotlin.explicitApi = ExplicitApiMode.Disabled
application {
mainClass.set("ru.mipt.npm.sat.SatServerKt")
}

View File

@ -14,12 +14,10 @@ import space.kscience.dataforge.meta.Null
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.html.meta
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.three.threeJsHeader
import kotlin.random.Random
@ -49,12 +47,7 @@ fun main() {
) {
div("flex-column") {
h1 { +"Satellite detector demo" }
vision {
meta(Canvas3DOptions {
controls.enabled = false
})
sat
}
vision { sat }
}
}

View File

@ -1,3 +1,20 @@
public final class space/kscience/visionforge/demo/MetaEditorDemo : tornadofx/View {
public fun <init> ()V
public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;
public final fun getMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta;
public synthetic fun getRoot ()Ljavafx/scene/Parent;
public fun getRoot ()Ljavafx/scene/control/SplitPane;
}
public final class space/kscience/visionforge/demo/MetaEditorDemoApp : tornadofx/App {
public fun <init> ()V
}
public final class space/kscience/visionforge/demo/MetaEditorDemoKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/solid/demo/DemoKt {
public static final fun demo (Lspace/kscience/visionforge/solid/demo/VisionLayout;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun demo$default (Lspace/kscience/visionforge/solid/demo/VisionLayout;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
@ -6,8 +23,25 @@ public final class space/kscience/visionforge/solid/demo/DemoKt {
public static final fun showcaseCSG (Lspace/kscience/visionforge/solid/demo/VisionLayout;)V
}
public final class space/kscience/visionforge/solid/demo/FXDemoApp : tornadofx/App {
public fun <init> ()V
public final fun getView ()Lspace/kscience/visionforge/solid/demo/FXDemoGrid;
public fun start (Ljavafx/stage/Stage;)V
}
public final class space/kscience/visionforge/solid/demo/FXDemoAppKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}
public final class space/kscience/visionforge/solid/demo/FXDemoGrid : tornadofx/View, space/kscience/visionforge/solid/demo/VisionLayout {
public fun <init> ()V
public fun getRoot ()Ljavafx/scene/Parent;
public synthetic fun render (Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;)V
public fun render (Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/solid/Solid;Lspace/kscience/dataforge/meta/Meta;)V
}
public abstract interface class space/kscience/visionforge/solid/demo/VisionLayout {
public abstract fun getSolids ()Lspace/kscience/visionforge/solid/Solids;
public abstract fun render (Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;)V
public static synthetic fun render$default (Lspace/kscience/visionforge/solid/demo/VisionLayout;Lspace/kscience/dataforge/names/Name;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)V
}

View File

@ -8,16 +8,6 @@ kscience {
jvm()
js{
binaries.executable()
browser{
commonWebpackConfig{
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
}
}
}
dependencies {
implementation(projects.visionforgeSolid)

View File

@ -24,11 +24,6 @@ fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGro
block()
ambientLight {
color(Colors.white)
intensity = 0.5
}
pointLight(0, 0, 1000) {
color(Colors.white)
intensity = 10.0
}
}
render(Name.parse(name), vision, meta)
@ -38,6 +33,10 @@ val canvasOptions = Canvas3DOptions {
size {
minSize = 400
}
axes {
size = 500.0
visible = true
}
camera {
distance = 600.0
latitude = PI / 6
@ -48,8 +47,6 @@ val canvasOptions = Canvas3DOptions {
fun VisionLayout<Solid>.showcase() {
demo("shapes", "Basic shapes") {
ambientLight()
axes(size = 500.0)
box(100.0, 100.0, 100.0) {
z = -110.0
color("teal")
@ -125,16 +122,13 @@ fun VisionLayout<Solid>.showcase() {
demo("extrude", "extruded shape") {
extruded {
shape {
polygon(32, 50)
polygon(8, 50)
}
for (i in 0..100) {
layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i))
}
rotationY = -PI / 2
material {
type = "lambert"
color(Colors.teal)
}
rotationX = -PI / 2
}
}
@ -167,15 +161,7 @@ fun VisionLayout<Solid>.showcase() {
}
demo("STL", "STL loaded from URL") {
stl("Menger_sponge_sample.stl") {
scale(100f)
material {
type = "phong"
color("red")
specularColor("blue")
}
}
//stl("https://ozeki.hu/attachments/116/Menger_sponge_sample.stl")
stl("https://ozeki.hu/attachments/116/Menger_sponge_sample.stl")
}
}

View File

@ -4,10 +4,10 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import org.w3c.dom.Document
import space.kscience.visionforge.html.Application
import space.kscience.visionforge.html.startApplication
import space.kscience.visionforge.Application
import space.kscience.visionforge.solid.x
import space.kscience.visionforge.solid.y
import space.kscience.visionforge.startApplication
import kotlin.random.Random
private class ThreeDemoApp : Application {

View File

@ -72,7 +72,7 @@ class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
}
}
val element = document.getElementById("output-$name") ?: error("Element not found")
ThreeCanvas(three, element, canvasOptions)
three.getOrCreateCanvas(element, canvasOptions)
}.render(vision)
}
}

View File

@ -46,7 +46,7 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
mesh.scale.z = properties.getValue(VALUE)?.number?.toDouble() ?: 1.0
//add listener to object properties
onPropertyChange(three.context) { name ->
onPropertyChange { name ->
when {
name == VALUE -> {
val value = properties.getValue(VALUE)?.int ?: 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,416 +0,0 @@
# Event Display Tutorial
In this tutorial, we will explore properties of Visions and build a simple front-end application. You may find a complete project [here](https://git.sciprog.center/teldufalsari/visionforge-event-display-demo).
__NOTE:__ You will need Kotlin Multiplatform 1.9.0 or higher to complete this tutorial!
### Starting the Project
We will use Idea's default project template for Kotlin Multiplatform. To initialize the project, go to *File -> New -> Project...*, Then choose *Full-Stack Web Application* project template and
*Kotlin Gradle* build system. Then select *Next -> Finish*. You will end up with a project with some sample code.
To check that everything is working correctly, run *application -> run* Gradle target. You should see a greeting page when you open `http://localhost:8080` in a web browser.
We will use Kotlin React as our main UI library and Ktor Netty both as a web server. Our event display frontend and server will reside in `jsMain` and `jvmMain` directories respectively.
Before we start, we have to load necessary dependencies:
* Add SciProgCentre maven repo in `build.gradle.kts` file:
```kotlin
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
// Add either the line below:
maven("https://repo.kotlin.link")
// Or this line:
maven("https://maven.sciprog.center/kscience")
}
```
* Add `visionforge-threejs-server` into the list of JS dependencies of your project:
```kotlin
kotlin {
sourceSets {
val jsMain by getting {
dependencies {
implementation("space.kscience:visionforge-threejs-server:0.3.0-dev-14")
}
}
}
}
```
Refresh build model in the Idea to make sure the dependencies are successfully resolved.
__NOTE:__ In previous versions of VisionForge, some imports may be broken. If these dependencies fail to resolve, replace `space.kscience:visionforge-threejs-server:0.3.0-dev-14` with `space.kscience:visionforge-threejs:0.3.0-dev-14`. The resulting bundle will lack a React component used in the tutorial (see "Managing Visions"). You may copy and paste it directly from either [VisionForge](https://git.sciprog.center/kscience/visionforge/src/branch/master/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt) or the [tutorial repo](https://git.sciprog.center/teldufalsari/visionforge-event-display-demo/src/branch/main/src/jsMain/kotlin/canvas/ThreeCanvasComponent.kt), or even come up with a better implementation if your own.
### Setting up Page Markup
We need to create a page layout and set up Netty to serve our page to clients. There is nothing special related to VisionForge, so feel free to copy and paste the code below.
File: `src/jvmMain/.../Server.kt`
```kotlin
// ... imports go here
fun HTML.index() {
head {
// Compatibility headers
meta { charset = "UTF-8" }
meta {
name = "viewport"
content = "width=device-width, initial-scale=1.0"
}
meta {
httpEquiv = "X-UA-Compatible"
content = "IE=edge"
}
title("VF Demo")
}
// Link to our react script
body {
script(src = "/static/vf-demo.js") {}
}
}
fun main() {
// Seting up Netty
embeddedServer(Netty, port = 8080, host = "127.0.0.1") {
routing {
get("/") {
call.respondHtml(HttpStatusCode.OK, HTML::index)
}
static("/static") {
resources()
}
}
}.start(wait = true)
}
```
File: `src/jsMain/.../Client.kt`
```kotlin
fun main() {
val container = document.createElement("div")
document.body!!.appendChild(container)
val eventDisplay = EventDisplay.create {}
createRoot(container).render(eventDisplay)
}
```
File: `src/jsMain/.../Display.kt`
```kotlin
// All markup goes here:
val EventDisplay = FC<Props> {
// Global CSS rules
Global {
styles {
"html,\n" +
"body" {
height = 100.vh
width = 100.vw
margin = 0.px
}
"body > div" {
height = 100.vh
width = 100.vw
display = Display.flex
flexDirection = FlexDirection.column
justifyContent = JustifyContent.start
alignItems = AlignItems.center
}
"*,\n" +
"*:before,\n" +
"*:after" {
boxSizing = BoxSizing.borderBox
}
}
}
div {
css {
height = 100.pct
width = 100.pct
display = Display.flex
flexDirection = FlexDirection.column
alignItems = AlignItems.center
}
div {
css {
width = 100.pct
display = Display.flex
flexDirection = FlexDirection.row
alignItems = AlignItems.center
justifyContent = JustifyContent.center
}
input {
css {
margin = 5.px
padding = 5.px
}
type = InputType.button
value = "Update Events"
}
input {
css {
margin = 5.px
padding = 5.px
}
type = InputType.button
value = "Update Geometry"
}
}
div {
css {
width = 98.pct
height = 1.pct
margin = 5.px
display = Display.flex
flexGrow = number(1.0)
justifyContent = JustifyContent.center
alignItems = AlignItems.center
backgroundColor = Color("#b3b3b3")
}
}
}
}
```
After setting everything up, you should see a gray rectangle with two buttons above it when opening `localhost:8080`.
### Managing Visions
We are approaching the main part of the tutorial - the place where we will create a working demo. In particle accelerator experiments, event displays are employed to visualise particle collision events. Essentially, it requires drawing a detector setup and visual interpretation of events: tracks, detector hits etc. Usually, a number of events share a common detector setup (e.g. if these events occured in a single experiment run). It makes sense to update and re-render only event information, while keeping detector geometry constant between updates.
Visions (namely, the `SolidGroup` class) allow us to create an object tree for our displayed event. `SolidGroup` can hold other Visions as its child nodes, access these nodes by names and update/delete them. We will use this property to update our event display efficiently.
To display Visions as actual 3D object, we will use `ThreePlugin` that renders Visions using *three.js* library. The plugin allows us to create a Three.js representation of a vision that will observe changes of its correspondent Vision. This way we can update only Visions without diving deep into three.js stuff. Using observable Visions is also efficient: Three.js representations are not generated from scratch after each Vision update but are modified too.
First, let's simulate data load operations:
* Add state variables to our `EventDisplay` React component. These variables will be treated as data loaded from a remote server. In real life, these may be JSON string with event data:
```kotlin
val EventDisplay = FC<Props> {
// ...
var eventData: kotlin.Float? by useState(null)
var geometryData: kotlin.Float? by useState(null)
// ...
}
```
* Write two simple functions that will convert data to a Vision. In this case, we will simply parameters of solids like color of size; in real life, these functions will usually take raw data and convert it into Visions.
```kotlin
fun generateEvents(radius: Float): SolidGroup {
val count = Random.nextInt(10, 20)
return SolidGroup {
repeat(count) {
sphere(radius) {
x = 5.0 * (Random.nextFloat() - 0.5)
y = 2.0 * (Random.nextFloat() - 0.5)
z = 2.0 * (Random.nextFloat() - 0.5)
color(Colors.red)
}
}
}
}
fun generateGeometry(distance: Float): SolidGroup {
return SolidGroup {
box(10, 3, 3) {
x = 0.0
y = -distance
z = 0.0
color(Colors.gray)
}
box(10, 3, 3) {
x = 0.0
y = distance
z = 0.0
color(Colors.gray)
}
}
}
```
* Then, let's create our main Vision and add a static light source:
```kotlin
val EventDisplay = FC<Props> {
// ...
val containedVision: SolidGroup by useState(SolidGroup {
ambientLight {
color(Colors.white)
}
})
// ...
}
```
* A `Context` object is required to hold plugins like `ThreePlugin`. It is also necessary to make Visions observable: we have to root our main Vision in the context. Declare a global `Context` in the same file with `EventDisplay` component:
```kotlin
val viewContext = Context {
plugin(Solids)
plugin(ThreePlugin)
}
```
* Import `ThreeCanvasComponent` from VisionForge. This is a React component that handles all display work. It creates three.js canvas, attaches it to its own parent element and creates and draws `Object3D` on the canvas. We will attach this component to a
separate React component. Note order for Visions to update their Three.js representations, these Visions need to be rooted in a `Context`. This way Visions will be observed for changes, and any such change will trigger an update of the corresponding Three.js object.
```kotlin
external interface EventViewProps: Props {
var displayedVision: Solid?
var context: Context
}
val EventView = FC<EventViewProps> { props ->
ThreeCanvasComponent {
solid = props.displayedVision
context = props.context
}
// Make displayedVision observed:
useEffect(props.displayedVision) {
props.displayedVision?.setAsRoot(props.context.visionManager)
}
}
```
__NOTE:__ If you had problems with dependency resolution, `ThreeCanvasComponent` may missing from your import scope. You may find a compatible implementation [here](https://git.sciprog.center/teldufalsari/visionforge-event-display-demo/src/branch/main/src/jsMain/kotlin/canvas/ThreeCanvasComponent.kt).
* Finally, we need to attach EventView to our main component and connect raw data updates to Vision updates using React hooks:
```kotlin
// ...
// Names used as keys to access and update Visions
// Refer to DataForge documentation for more details
val EVENTS_NAME = "DEMO_EVENTS".parseAsName(false)
val GEOMETRY_NAME = "DEMO_GEOMETRY".parseAsName(false)
// ...
val EventDisplay = FC<Props> {
// ...
useEffect(eventData) {
eventData?.let {
containedVision.setChild(EVENTS_NAME, generateEvents(it))
}
}
useEffect(geometryData) {
geometryData?.let {
containedVision.setChild(GEOMETRY_NAME, generateGeometry(it))
}
}
// ...
div {
// ...
div {
css {
width = 98.pct
height = 1.pct
flexGrow = number(1.0)
margin = 5.px
display = Display.flex
justifyContent = JustifyContent.center
alignItems = AlignItems.center
}
// Replace the gray rectangle with an EventView:
EventView {
displayedVision = containedVision
context = viewContext
}
}
}
// ...
}
```
When we press either of the buttons, corresponding raw data changes. This update triggers `UseEffect` hook, which generates new event or geometry data and replaces the old data in the main Vision. Three.js representation is then updated to match our new Vision, so that changes are visible on the canvas.
Recompile the project and go on `http://localhost:8080`. See how the displayed scene changes with each click: for example, when you update geometry, only the distance between "magnets" varies, but spheres remain intact.
### Clearing the Scene
We can erase children Visions from the scene completely. To do so, we cat pass `null` to the function `setChild` as `child` argument. Add these lines to the hooks that update Visions to remove the corresponding Vision from our diplayed `SolidGroup` when raw data changes to `null`:
```kotlin
useEffect(eventData) {
// ...
if (eventData == null) {
containedVision.setChild(EVENT_NAME, null)
}
}
useEffect(geometryData) {
// ...
if (geometryData == null) {
containedVision.setChild(GEOMETRY_NAME, null)
}
}
```
To test how this works, let's create an erase button that will completely clear the scene:
```kotlin
val EventDisplay = FC<Props> {
// ...
div {
// ...
input {
css {
margin = 5.px
padding = 5.px
backgroundColor = NamedColor.lightcoral
color = NamedColor.white
}
type = InputType.button
value = "Clear Scene"
onClick = {
geometryData = null
eventData = null
}
}
}
// ...
}
```
![Picture of an event display with a red button with a caption "Clear Scene" added to the two previous buttons](../images/event-display-final.png "Scene clearing function")
### Making Selection Fine-Grained
You may feel annoyed by how selection works in our demo. That's right, selecting the whole detector or the entire event array is not that useful. This is due to the fact that VisionForge selects object based on names. We used names to distinguish SolidGroups, but in fact not only groups but every single Vision can have a name. But when we were randomly generating Vision, we did not use any names, did we? Right, Vision can be nameless, in which case they are treated as a monolithic object together with their parent. So it should be clear now that when we were selecting a single rectangle, we were in fact selecting the whole pair of rectangles and the other one went lit up as well.
Fortunately, every `Solid` constructor takes a `name` parameter after essential parameters, so it should be easy to fix it. Go to the generator functions and add the change construction invocations to the following:
```kotlin
fun generateGeometry(distance: Float): SolidGroup {
return SolidGroup {
box(10, 3, 3, "Magnet1") {
// ...
}
box(10, 3, 3, "Magnet2") {
// ...
}
}
}
```
For the events part, we will use the index in a loop as a name:
```kotlin
fun generateEvents(radius: Float): SolidGroup {
// ...
repeat(count) {
sphere(radius, it.toString()) {
// ...
}
```
After you update the build, it should be possible to select only one sphere or rectangle:
![Picture of an event display with only one sphere between the magnets selected](../images/event-display-selection.png "Selection demonstration")

View File

@ -1,7 +1,13 @@
kotlin.code.style=official
kotlin.mpp.stability.nowarn=true
kotlin.js.compiler=ir
#kotlin.incremental.js.ir=true
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx4G
toolsVersion=0.15.2-kotlin-2.0.0-RC1
org.jetbrains.compose.experimental.jscanvas.enabled=true
toolsVersion=0.15.2-kotlin-2.0.0-Beta2
#kotlin.experimental.tryK2=true
#kscience.wasm.disabled=true

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -18,6 +18,7 @@ pluginManagement {
id("space.kscience.gradle.project") version toolsVersion
id("space.kscience.gradle.mpp") version toolsVersion
id("space.kscience.gradle.jvm") version toolsVersion
id("space.kscience.gradle.js") version toolsVersion
}
}
@ -39,9 +40,13 @@ dependencyResolutionManagement {
}
include(
// ":ui",
":ui:react",
":ui:ring",
// ":ui:material",
":ui:bootstrap",
// ":ui:compose",
":visionforge-core",
":visionforge-compose-html",
":visionforge-compose-multiplatform",
":visionforge-solid",
// ":visionforge-fx",
":visionforge-threejs",
@ -59,7 +64,6 @@ include(
":demo:playground",
// ":demo:plotly-fx",
":demo:js-playground",
":demo:compose-desktop-demo",
":visionforge-jupyter",
":visionforge-jupyter:visionforge-jupyter-common"
)

4
ui/README.md Normal file
View File

@ -0,0 +1,4 @@
# Module ui

4
ui/bootstrap/README.md Normal file
View File

@ -0,0 +1,4 @@
# Module bootstrap

View File

@ -0,0 +1,19 @@
plugins {
id("space.kscience.gradle.mpp")
}
val dataforgeVersion: String by rootProject.extra
kscience{
js()
jsMain{
dependencies {
api(project(":visionforge-solid"))
api(project(":ui:react"))
implementation(npm("file-saver", "2.0.2"))
implementation(npm("bootstrap","4.6.0"))
implementation(npm("jquery","3.5.1"))
implementation(npm("popper.js","1.16.1"))
}
}
}

View File

@ -0,0 +1,121 @@
package space.kscience.visionforge.bootstrap
public fun useBootstrap(){
kotlinext.js.require<dynamic>("bootstrap/dist/css/bootstrap.min.css")
kotlinext.js.require<dynamic>("bootstrap")
}
//public inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
// div("card w-100") {
// div("card-body") {
// h3(classes = "card-title") { +title }
// block()
// }
// }
//}
//public typealias SectionsBuilder = MutableList<Pair<String, DIV.() -> Unit>>
//
//public fun SectionsBuilder.entry(title: String, builder: DIV.() -> Unit) {
// add(title to builder)
//}
//public fun TagConsumer<HTMLElement>.accordion(id: String, elements: List<Pair<String, DIV.() -> Unit>>) {
// div("container-fluid") {
// div("accordion") {
// this.id = id
// elements.forEachIndexed { index, (title, builder) ->
// val headerID = "${id}-${index}-heading"
// val collapseID = "${id}-${index}-collapse"
// div("card") {
// div("card-header") {
// this.id = headerID
// h5("mb-0") {
// button(classes = "btn btn-link collapsed", type = ButtonType.button) {
// attributes["data-toggle"] = "collapse"
// attributes["data-target"] = "#$collapseID"
// attributes["aria-expanded"] = "false"
// attributes["aria-controls"] = collapseID
// +title
// }
// }
// }
// div("collapse") {
// this.id = collapseID
// attributes["aria-labelledby"] = headerID
// attributes["data-parent"] = "#$id"
// div("card-body", block = builder)
// }
// }
// }
// }
// }
//}
//public fun TagConsumer<HTMLElement>.accordion(id: String, builder: AccordionBuilder.() -> Unit) {
// val list = ArrayList<Pair<String, DIV.() -> Unit>>().apply(builder)
// accordion(id, list)
//}
//public fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer<HTMLElement>.() -> Unit = {}) {
// clear()
// append {
// accordion("controls") {
// entry("Settings") {
// div("row") {
// div("col-2") {
// label("checkbox-inline") {
// input(type = InputType.checkBox) {
// checked = canvas.axes.visible
// onChangeFunction = {
// canvas.axes.visible = checked
// }
// }
// +"Axes"
// }
// }
// div("col-1") {
// button {
// +"Export"
// onClickFunction = {
// val json = (canvas.content as? SolidGroup)?.let { group ->
// val visionManager = canvas.context.plugins.fetch(SolidManager).visionManager
// visionManager.encodeToString(group)
// }
// if (json != null) {
// saveData(it, "object.json", "text/json") {
// json
// }
// }
// }
// }
// }
// }
// }
// entry("Layers") {
// div("row") {
// (0..11).forEach { layer ->
// div("col-1") {
// label { +layer.toString() }
// input(type = InputType.checkBox) {
// if (layer == 0) {
// checked = true
// }
// onChangeFunction = {
// if (checked) {
// canvas.camera.layers.enable(layer)
// } else {
// canvas.camera.layers.disable(layer)
// }
// }
// }
// }
// }
// }
// }
// }
// block()
// }
//}

View File

@ -0,0 +1,77 @@
package space.kscience.visionforge.bootstrap
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.css.*
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import org.w3c.files.Blob
import org.w3c.files.BlobPropertyBag
import react.FC
import react.Props
import react.RBuilder
import react.dom.attrs
import react.dom.button
import react.fc
import space.kscience.visionforge.Vision
import space.kscience.visionforge.encodeToString
import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.react.propertyEditor
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
event.stopPropagation();
event.preventDefault();
val fileSaver = kotlinext.js.require<dynamic>("file-saver")
val blob = Blob(arrayOf(dataBuilder()), BlobPropertyBag("$mimeType;charset=utf-8"))
fileSaver.saveAs(blob, fileName)
}
public fun RBuilder.canvasControls(canvasOptions: Canvas3DOptions, vision: Vision?) {
child(CanvasControls) {
attrs {
this.canvasOptions = canvasOptions
this.vision = vision
}
}
}
public external interface CanvasControlsProps : Props {
public var canvasOptions: Canvas3DOptions
public var vision: Vision?
}
public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props ->
flexColumn {
flexRow {
css {
border = Border(1.px, BorderStyle.solid, Color.blue)
padding = Padding(4.px)
}
props.vision?.let { vision ->
button {
+"Export"
attrs {
onClickFunction = {
val json = vision.encodeToString()
saveData(it, "object.json", "text/json") {
json
}
}
}
}
}
}
@OptIn(DelicateCoroutinesApi::class)
propertyEditor(
scope = props.vision?.manager?.context ?: GlobalScope,
properties = props.canvasOptions.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = false
)
}
}

View File

@ -0,0 +1,181 @@
package space.kscience.visionforge.bootstrap
import kotlinx.html.ButtonType
import kotlinx.html.DIV
import kotlinx.html.id
import kotlinx.html.js.onClickFunction
import react.RBuilder
import react.dom.*
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.length
import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
import styled.styledNav
public inline fun RBuilder.card(title: String, crossinline block: StyledDOMBuilder<DIV>.() -> Unit): Unit =
styledDiv {
css {
+"card"
+"w-100"
}
styledDiv {
css {
+"card-body"
}
h3(classes = "card-title") {
+title
}
block()
}
}
public fun RBuilder.accordion(
id: String,
elements: List<Pair<String, StyledDOMBuilder<DIV>.() -> Unit>>,
): Unit = styledDiv {
css {
+"accordion"
//+"p-1"
}
attrs {
this.id = id
}
elements.forEachIndexed { index, (title, builder) ->
val headerID = "${id}-${index}-heading"
val collapseID = "${id}-${index}-collapse"
div("card p-0 m-0") {
div("card-header") {
attrs {
this.id = headerID
}
h5("mb-0") {
button(classes = "btn btn-link collapsed", type = ButtonType.button) {
attrs {
attributes["data-toggle"] = "collapse"
attributes["data-target"] = "#$collapseID"
attributes["aria-expanded"] = "false"
attributes["aria-controls"] = collapseID
}
+title
}
}
}
div("collapse") {
attrs {
this.id = collapseID
attributes["aria-labelledby"] = headerID
attributes["data-parent"] = "#$id"
}
styledDiv {
css {
+"card-body"
}
builder()
}
}
}
}
}
public fun RBuilder.nameCrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit): Unit = styledNav {
css {
+"p-0"
}
attrs {
attributes["aria-label"] = "breadcrumb"
}
ol("breadcrumb") {
li("breadcrumb-item") {
button(classes = "btn btn-link p-0") {
+rootTitle
attrs {
onClickFunction = {
link(Name.EMPTY)
}
}
}
}
if (name != null) {
val tokens = ArrayList<NameToken>(name.length)
name.tokens.forEach { token ->
tokens.add(token)
val fullName = Name(tokens.toList())
li("breadcrumb-item") {
button(classes = "btn btn-link p-0") {
+token.toString()
attrs {
onClickFunction = {
console.log("Selected = $fullName")
link(fullName)
}
}
}
}
}
}
}
}
public typealias RSectionsBuilder = MutableList<Pair<String, StyledDOMBuilder<DIV>.() -> Unit>>
public fun RSectionsBuilder.entry(title: String, builder: StyledDOMBuilder<DIV>.() -> Unit) {
add(title to builder)
}
public fun RBuilder.accordion(id: String, builder: RSectionsBuilder.() -> Unit): Unit {
val list = ArrayList<Pair<String, StyledDOMBuilder<DIV>.() -> Unit>>().apply(builder)
accordion(id, list)
}
public enum class ContainerSize(public val suffix: String) {
DEFAULT(""),
SM("-sm"),
MD("-md"),
LG("-lg"),
XL("-xl"),
FLUID("-fluid")
}
public inline fun RBuilder.container(
size: ContainerSize = ContainerSize.FLUID,
block: StyledDOMBuilder<DIV>.() -> Unit,
): Unit = styledDiv {
css {
classes.add("container${size.suffix}")
}
block()
}
public enum class GridMaxSize(public val suffix: String) {
NONE(""),
SM("-sm"),
MD("-md"),
LG("-lg"),
XL("-xl")
}
public inline fun RBuilder.gridColumn(
weight: Int? = null,
maxSize: GridMaxSize = GridMaxSize.NONE,
block: StyledDOMBuilder<DIV>.() -> Unit,
): Unit = styledDiv {
val weightSuffix = weight?.let { "-$it" } ?: ""
css {
classes.add("col${maxSize.suffix}$weightSuffix")
}
block()
}
public inline fun RBuilder.gridRow(
block: StyledDOMBuilder<DIV>.() -> Unit,
): Unit = styledDiv {
css {
classes.add("row")
}
block()
}

View File

@ -0,0 +1,86 @@
package space.kscience.visionforge.bootstrap
import kotlinx.html.DIV
import kotlinx.html.classes
import kotlinx.html.js.onClickFunction
import react.*
import react.dom.attrs
import react.dom.button
import react.dom.li
import react.dom.ul
import space.kscience.visionforge.react.flexColumn
import styled.StyledDOMBuilder
import styled.styledDiv
public external interface TabProps : PropsWithChildren {
public var id: String
public var title: String?
}
@JsExport
public val Tab: FC<TabProps> = fc { props ->
props.children()
}
public external interface TabPaneProps : PropsWithChildren {
public var activeTab: String?
}
@JsExport
public val TabPane: FC<TabPaneProps> = fc("TabPane") { props ->
var activeTab: String? by useState(props.activeTab)
val children: Array<out ReactElement<*>?> = Children.map(props.children) {
it.asElementOrNull()
} ?: emptyArray()
val childrenProps = children.mapNotNull {
it?.props?.unsafeCast<TabProps>()
}
flexColumn {
ul("nav nav-tabs") {
childrenProps.forEach { cp ->
li("nav-item") {
button(classes = "nav-link") {
+(cp.title ?: cp.id)
attrs {
if (cp.id == activeTab) {
classes = classes + "active"
}
onClickFunction = {
activeTab = cp.id
}
}
}
}
}
}
children.find { (it?.props?.unsafeCast<TabProps>())?.id == activeTab }?.let {
child(it)
}
}
}
public class TabBuilder(internal val parentBuilder: RBuilder) {
public fun tab(id: String, title: String? = null, builder: StyledDOMBuilder<DIV>.() -> Unit) {
parentBuilder.child(Tab) {
attrs {
this.id = id
this.title = title
}
styledDiv {
builder()
}
}
}
}
public inline fun RBuilder.tabPane(activeTab: String? = null, crossinline builder: TabBuilder.() -> Unit) {
child(TabPane) {
attrs {
this.activeTab = activeTab
}
TabBuilder(this).builder()
}
}

View File

@ -0,0 +1,80 @@
package space.kscience.visionforge.bootstrap
import kotlinx.css.*
import react.FC
import react.PropsWithChildren
import react.RBuilder
import react.dom.h2
import react.fc
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.isEmpty
import space.kscience.visionforge.Vision
import space.kscience.visionforge.react.visionTree
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
import styled.styledDiv
public external interface ThreeControlsProps : PropsWithChildren {
public var canvasOptions: Canvas3DOptions
public var vision: Vision?
public var selected: Name?
public var onSelect: (Name) -> Unit
}
@JsExport
public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
tabPane(if (props.selected != null) "Properties" else null) {
tab("Canvas") {
card("Canvas configuration") {
canvasControls(props.canvasOptions, props.vision)
}
}
tab("Tree") {
css {
border = Border(1.px, BorderStyle.solid, Color.lightGray)
padding = Padding(10.px)
}
h2 { +"Object tree" }
styledDiv {
css {
flex = Flex(1.0, 1.0, FlexBasis.inherit)
}
props.vision?.let {
visionTree(it, props.selected, props.onSelect)
}
}
}
tab("Properties") {
props.selected.let { selected ->
val selectedObject: Vision? = when {
selected == null -> null
selected.isEmpty() -> props.vision
else -> (props.vision as? SolidGroup)?.get(selected)
}
if (selectedObject != null) {
visionPropertyEditor(selectedObject, key = selected)
}
}
}
this.parentBuilder.run {
props.children()
}
}
}
public fun RBuilder.threeControls(
canvasOptions: Canvas3DOptions,
vision: Vision?,
selected: Name?,
onSelect: (Name) -> Unit = {},
builder: TabBuilder.() -> Unit = {},
): Unit = child(ThreeControls) {
attrs {
this.canvasOptions = canvasOptions
this.vision = vision
this.selected = selected
this.onSelect = onSelect
}
TabBuilder(this).builder()
}

View File

@ -0,0 +1,71 @@
package space.kscience.visionforge.bootstrap
import org.w3c.dom.Element
import react.RBuilder
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.isEmpty
import space.kscience.visionforge.Vision
import space.kscience.visionforge.getStyle
import space.kscience.visionforge.react.EditorPropertyState
import space.kscience.visionforge.react.PropertyEditor
import space.kscience.visionforge.react.metaViewer
import space.kscience.visionforge.react.render
import space.kscience.visionforge.root
import space.kscience.visionforge.solid.SolidReference
import space.kscience.visionforge.styles
public fun RBuilder.visionPropertyEditor(
vision: Vision,
descriptor: MetaDescriptor? = vision.descriptor,
key: Any? = null,
) {
card("Properties") {
child(PropertyEditor) {
attrs {
this.key = key?.toString()
this.meta = vision.properties.root()
this.updates = vision.properties.changes
this.descriptor = descriptor
this.scope = vision.manager?.context ?: error("Orphan vision could not be observed")
this.getPropertyState = { name ->
val ownMeta = vision.properties.own?.getMeta(name)
if (ownMeta != null && !ownMeta.isEmpty()) {
EditorPropertyState.Defined
} else if (vision.properties.root().getValue(name) != null) {
// TODO differentiate
EditorPropertyState.Default()
} else {
EditorPropertyState.Undefined
}
}
}
}
}
val styles = if (vision is SolidReference) {
(vision.styles + vision.prototype.styles).distinct()
} else {
vision.styles
}
if (styles.isNotEmpty()) {
card("Styles") {
accordion("styles") {
styles.forEach { styleName ->
val style = vision.getStyle(styleName)
if (style != null) {
entry(styleName) {
metaViewer(style)
}
}
}
}
}
}
}
public fun Element.visionPropertyEditor(
item: Vision,
descriptor: MetaDescriptor? = item.descriptor,
): Unit = space.kscience.visionforge.react.createRoot(this).render {
visionPropertyEditor(item, descriptor = descriptor)
}

View File

@ -0,0 +1,56 @@
/*full height*/
html, body {
height: 100%;
width: 100%;
}
.container-fluid { height: inherit; }
/* Remove default bullets */
ul, .tree {
list-style-type: none;
}
/* Style the caret/arrow */
.tree-caret {
cursor: pointer;
user-select: none; /* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
.tree-leaf{
user-select: none;
display: inline-block;
}
.tree-leaf::before {
content: "\25C6";
color: black;
display: inline-block;
margin-right: 6px;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down::before {
transform: rotate(90deg);
}
.tree-label-inactive {
color: lightgrey;
}
.tree-label-selected{
background-color: lightblue;
}
.no-padding{
padding: 0;
}

View File

@ -0,0 +1,41 @@
plugins {
id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
// id("com.android.library")
}
kscience{
jvm()
js()
// wasm()
}
kotlin {
// android()
sourceSets {
val commonMain by getting {
dependencies {
}
}
val jvmMain by getting {
dependencies {
api(compose.runtime)
api(compose.foundation)
api(compose.material)
api(compose.preview)
}
}
val jsMain by getting{
dependencies {
api(compose.html.core)
api("app.softwork:bootstrap-compose:0.1.15")
api("app.softwork:bootstrap-compose-icons:0.1.15")
api(projects.visionforge.visionforgeThreejs)
}
}
}
}

View File

@ -1,4 +1,4 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import org.jetbrains.compose.web.css.AlignItems
@ -10,6 +10,7 @@ import org.jetbrains.compose.web.dom.Text
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
@ -63,7 +64,7 @@ private fun MetaViewerItem(root: Meta, name: Name, rootDescriptor: MetaDescripto
classes(TreeStyles.tree)
}) {
val keys = buildSet {
descriptorItem?.nodes?.keys?.forEach {
descriptorItem?.children?.keys?.forEach {
add(NameToken(it))
}
actualMeta!!.items.keys.let { addAll(it) }

View File

@ -1,7 +1,10 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.dom.Li
import org.jetbrains.compose.web.dom.Nav
import org.jetbrains.compose.web.dom.Ol
import org.jetbrains.compose.web.dom.Text
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.length
@ -10,29 +13,22 @@ import space.kscience.dataforge.names.length
public fun NameCrumbs(name: Name?, link: (Name) -> Unit): Unit = Nav({
attr("aria-label","breadcrumb")
}) {
Ol({
classes("breadcrumb")
style {
property("--bs-breadcrumb-divider", "'.'")
property("--bs-breadcrumb-item-padding-x", ".1rem")
}
}) {
Ol({classes("breadcrumb")}) {
Li({
classes("breadcrumb-item")
onClick {
link(Name.EMPTY)
}
}) {
A("#") {
Text("\u2302")
}
}
if (name != null) {
val tokens = ArrayList<NameToken>(name.length)
name.tokens.forEach { token ->
tokens.add(token)
val fullName = Name(tokens.toList())
Text(".")
Li({
classes("breadcrumb-item")
if(tokens.size == name.length) classes("active")
@ -40,11 +36,9 @@ public fun NameCrumbs(name: Name?, link: (Name) -> Unit): Unit = Nav({
link(fullName)
}
}) {
A("#") {
Text(token.toString())
}
}
}
}
}
}

View File

@ -1,13 +1,11 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch
import org.jetbrains.compose.web.attributes.ButtonType
import org.jetbrains.compose.web.attributes.disabled
import org.jetbrains.compose.web.attributes.type
import org.jetbrains.compose.web.css.AlignItems
import org.jetbrains.compose.web.css.alignItems
import org.jetbrains.compose.web.css.px
@ -19,8 +17,9 @@ import org.jetbrains.compose.web.dom.Text
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.ObservableMutableMeta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.ValueRestriction
import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.remove
import space.kscience.dataforge.names.*
import space.kscience.visionforge.hidden
@ -30,33 +29,35 @@ import space.kscience.visionforge.hidden
* The display state of a property
*/
public sealed class EditorPropertyState {
public data object Defined : EditorPropertyState()
public data class Default(public val source: String = "unknown") : EditorPropertyState()
public data object Undefined : EditorPropertyState()
public object Defined : EditorPropertyState()
public class Default(public val source: String = "unknown") : EditorPropertyState()
public object Undefined : EditorPropertyState()
}
/**
* @param rootMeta Root config object - always non-null
* @param rootDescriptor Full path to the displayed node in [rootMeta]. Could be empty
* @param meta Root config object - always non-null
* @param rootDescriptor Full path to the displayed node in [meta]. Could be empty
*/
@Composable
public fun PropertyEditor(
rootMeta: MutableMeta,
scope: CoroutineScope,
meta: MutableMeta,
getPropertyState: (Name) -> EditorPropertyState,
updates: Flow<Name>,
name: Name,
rootDescriptor: MetaDescriptor?,
name: Name = Name.EMPTY,
rootDescriptor: MetaDescriptor? = null,
initialExpanded: Boolean? = null,
) {
var expanded: Boolean by remember { mutableStateOf(initialExpanded ?: true) }
val descriptor: MetaDescriptor? by derivedStateOf { rootDescriptor?.get(name) }
var displayedValue by remember { mutableStateOf(rootMeta.getValue(name)) }
val descriptor: MetaDescriptor? = remember(rootDescriptor, name) { rootDescriptor?.get(name) }
var property: MutableMeta by remember { mutableStateOf(meta.getOrCreate(name)) }
var editorPropertyState: EditorPropertyState by remember { mutableStateOf(getPropertyState(name)) }
val keys by derivedStateOf {
val keys = remember(descriptor) {
buildSet {
descriptor?.nodes?.filterNot {
descriptor?.children?.filterNot {
it.key.startsWith("@") || it.value.hidden
}?.forEach {
add(NameToken(it.key))
@ -68,13 +69,13 @@ public fun PropertyEditor(
val token = name.lastOrNull()?.toString() ?: "Properties"
fun update() {
displayedValue = rootMeta.getValue(name)
property = meta.getOrCreate(name)
editorPropertyState = getPropertyState(name)
}
LaunchedEffect(rootMeta) {
LaunchedEffect(meta) {
updates.collect { updatedName ->
if (name.startsWith(updatedName)) {
if (updatedName == name) {
update()
}
}
@ -85,7 +86,6 @@ public fun PropertyEditor(
alignItems(AlignItems.Center)
}
}) {
//if node has children
if (keys.isNotEmpty()) {
Span({
classes(TreeStyles.treeCaret)
@ -97,42 +97,39 @@ public fun PropertyEditor(
}
Span({
classes(TreeStyles.treeLabel)
when (editorPropertyState) {
is EditorPropertyState.Default, EditorPropertyState.Undefined -> {
if (editorPropertyState != EditorPropertyState.Defined) {
classes(TreeStyles.treeLabelInactive)
}
EditorPropertyState.Defined -> {}
}
}) {
Text(token)
}
if (!name.isEmpty() && descriptor?.valueRestriction != ValueRestriction.ABSENT) {
if (!name.isEmpty() && descriptor?.valueRequirement != ValueRequirement.ABSENT) {
Div({
style {
width(160.px)
marginAll(1.px, 5.px)
}
}) {
ValueChooser(descriptor, editorPropertyState, displayedValue) {
rootMeta.setValue(name, it)
update()
ValueChooser(descriptor, editorPropertyState, property.value) {
property.value = it
editorPropertyState = getPropertyState(name)
}
}
}
if (!name.isEmpty()) {
Button(attrs = {
type(ButtonType.Button)
if(editorPropertyState != EditorPropertyState.Defined) disabled()
classes("btn-close")
Button({
classes(TreeStyles.propertyEditorButton)
if (editorPropertyState != EditorPropertyState.Defined) {
disabled()
} else {
onClick {
rootMeta.remove(name)
meta.remove(name)
update()
}
})
}
}) {
Text("\u00D7")
}
}
}
if (expanded) {
@ -143,7 +140,7 @@ public fun PropertyEditor(
Div({
classes(TreeStyles.treeItem)
}) {
PropertyEditor(rootMeta, getPropertyState, updates, name + token, rootDescriptor, expanded)
PropertyEditor(scope, meta, getPropertyState, updates, name + token, descriptor, expanded)
}
}
}
@ -152,13 +149,14 @@ public fun PropertyEditor(
@Composable
public fun PropertyEditor(
scope: CoroutineScope,
properties: ObservableMutableMeta,
descriptor: MetaDescriptor? = null,
expanded: Boolean? = null,
) {
val scope = rememberCoroutineScope()
PropertyEditor(
rootMeta = properties,
scope = scope,
meta = properties,
getPropertyState = { name ->
if (properties[name] != null) {
EditorPropertyState.Defined
@ -175,7 +173,9 @@ public fun PropertyEditor(
}
}
awaitClose { properties.removeListener(scope) }
invokeOnClose {
properties.removeListener(scope)
}
},
name = Name.EMPTY,
rootDescriptor = descriptor,

View File

@ -0,0 +1,102 @@
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLLIElement
public class ComposeTab(
public val key: String,
public val title: String,
public val content: ContentBuilder<HTMLDivElement>,
public val disabled: Boolean,
public val titleExt: ContentBuilder<HTMLLIElement>,
)
@Composable
public fun Tabs(tabs: List<ComposeTab>, activeKey: String) {
var active by remember(activeKey) { mutableStateOf(activeKey) }
Div({ classes("card", "text-center") }) {
Div({ classes("card-header") }) {
Ul({ classes("nav", "nav-tabs", "card-header-tabs") }) {
tabs.forEach { tab ->
Li({
classes("nav-item")
}) {
A(attrs = {
classes("nav-link")
if (active == tab.key) {
classes("active")
}
if (tab.disabled) {
classes("disabled")
}
onClick {
active = tab.key
}
}) {
Text(tab.title)
}
tab.titleExt.invoke(this)
}
}
}
}
tabs.find { it.key == active }?.let { tab ->
Div({ classes("card-body") }) {
tab.content.invoke(this)
}
}
}
}
public class TabBuilder internal constructor(public val key: String) {
private var title: String = key
public var disabled: Boolean = false
private var content: ContentBuilder<HTMLDivElement> = {}
private var titleExt: ContentBuilder<HTMLLIElement> = {}
@Composable
public fun Content(content: ContentBuilder<HTMLDivElement>) {
this.content = content
}
@Composable
public fun Title(title: String, titleExt: ContentBuilder<HTMLLIElement> = {}) {
this.title = title
this.titleExt = titleExt
}
internal fun build(): ComposeTab = ComposeTab(
key,
title,
content,
disabled,
titleExt
)
}
public class TabsBuilder {
public var active: String = ""
internal val tabs: MutableList<ComposeTab> = mutableListOf()
@Composable
public fun Tab(key: String, builder: @Composable TabBuilder.() -> Unit) {
tabs.add(TabBuilder(key).apply { builder() }.build())
}
public fun addTab(tab: ComposeTab) {
tabs.add(tab)
}
}
@Composable
public fun Tabs(builder: @Composable TabsBuilder.() -> Unit) {
val result = TabsBuilder().apply { builder() }
Tabs(result.tabs, result.active)
}

View File

@ -0,0 +1,52 @@
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import kotlinx.dom.clear
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreeCanvas
import space.kscience.visionforge.solid.three.ThreePlugin
@Composable
public fun ThreeCanvas(
context: Context,
options: Canvas3DOptions?,
solid: Solid?,
selected: Name?,
) {
val three: ThreePlugin by derivedStateOf { context.request(ThreePlugin) }
Div({
style {
maxWidth(100.vw)
maxHeight(100.vh)
width(100.percent)
height(100.percent)
}
}) {
var canvas: ThreeCanvas? = null
DisposableEffect(options) {
canvas = ThreeCanvas(three, scopeElement, options ?: Canvas3DOptions())
onDispose {
scopeElement.clear()
canvas = null
}
}
LaunchedEffect(solid) {
if (solid != null) {
canvas?.render(solid)
} else {
canvas?.clear()
}
}
LaunchedEffect(selected) {
canvas?.select(selected)
}
}
}

View File

@ -0,0 +1,80 @@
package space.kscience.visionforge.compose
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Button
import org.jetbrains.compose.web.dom.Text
import org.w3c.files.Blob
import org.w3c.files.BlobPropertyBag
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.encodeToString
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@Composable
internal fun CanvasControls(
vision: Vision?,
options: Canvas3DOptions,
) {
FlexColumn {
FlexRow({
style {
border {
width(1.px)
style(LineStyle.Solid)
color(Color("blue"))
}
padding(4.px)
}
}) {
vision?.let { vision ->
Button({
onClick { event ->
val json = vision.encodeToString()
event.stopPropagation();
event.preventDefault();
val fileSaver = kotlinext.js.require<dynamic>("file-saver")
val blob = Blob(arrayOf(json), BlobPropertyBag("text/json;charset=utf-8"))
fileSaver.saveAs(blob, "object.json") as Unit
}
}) {
Text("Export")
}
}
}
PropertyEditor(
scope = vision?.manager?.context ?: Global,
properties = options.meta,
descriptor = Canvas3DOptions.descriptor,
expanded = false
)
}
}
@Composable
public fun ThreeControls(
vision: Vision?,
canvasOptions: Canvas3DOptions,
selected: Name?,
onSelect: (Name?) -> Unit,
tabBuilder: @Composable TabsBuilder.() -> Unit = {},
) {
Tabs {
active = "Tree"
vision?.let { vision ->
Tab("Tree") {
CardTitle("Vision tree")
VisionTree(vision, Name.EMPTY, selected, onSelect)
}
}
Tab("Settings") {
CardTitle("Canvas configuration")
CanvasControls(vision, canvasOptions)
}
tabBuilder()
}
}

View File

@ -0,0 +1,169 @@
@file:OptIn(ExperimentalComposeWebApi::class)
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import app.softwork.bootstrapcompose.Card
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.launch
import org.jetbrains.compose.web.ExperimentalComposeWebApi
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.*
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.isEmpty
import space.kscience.visionforge.*
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@Composable
public fun ThreeCanvasWithControls(
solids: Solids,
builderOfSolid: Deferred<Solid?>,
initialSelected: Name?,
options: Canvas3DOptions?,
tabBuilder: @Composable TabsBuilder.() -> Unit = {},
) {
var selected: Name? by remember { mutableStateOf(initialSelected) }
var solid: Solid? by remember { mutableStateOf(null) }
LaunchedEffect(builderOfSolid) {
solids.context.launch {
solid = builderOfSolid.await()
//ensure that the solid is properly rooted
if (solid?.parent == null) {
solid?.setAsRoot(solids.context.visionManager)
}
}
}
val optionsWithSelector = remember(options) {
(options ?: Canvas3DOptions()).apply {
this.onSelect = {
selected = it
}
}
}
val selectedVision: Vision? = remember(builderOfSolid, selected) {
selected?.let {
when {
it.isEmpty() -> solid
else -> (solid as? SolidGroup)?.get(it)
}
}
}
FlexRow({
style {
height(100.percent)
width(100.percent)
flexWrap(FlexWrap.Wrap)
alignItems(AlignItems.Stretch)
alignContent(AlignContent.Stretch)
}
}) {
FlexColumn({
style {
height(100.percent)
minWidth(600.px)
flex(10, 1, 600.px)
position(Position.Relative)
}
}) {
if (solid == null) {
Div({
style {
position(Position.Fixed)
width(100.percent)
height(100.percent)
zIndex(1000)
top(40.percent)
left(0.px)
opacity(0.5)
filter {
opacity(50.percent)
}
}
}) {
Div({ classes("d-flex", " justify-content-center") }) {
Div({
classes("spinner-grow", "text-primary")
style {
width(3.cssRem)
height(3.cssRem)
zIndex(20)
}
attr("role", "status")
}) {
Span({ classes("sr-only") }) { Text("Loading 3D vision") }
}
}
}
} else {
ThreeCanvas(solids.context, optionsWithSelector, solid, selected)
}
selectedVision?.let { vision ->
Div({
style {
position(Position.Absolute)
top(5.px)
right(5.px)
width(450.px)
}
}) {
Card(
headerAttrs = {
// border = true
},
header = {
NameCrumbs(selected) { selected = it }
}
) {
PropertyEditor(
scope = solids.context,
meta = vision.properties.root(),
getPropertyState = { name ->
if (vision.properties.own?.get(name) != null) {
EditorPropertyState.Defined
} else if (vision.properties.root()[name] != null) {
// TODO differentiate
EditorPropertyState.Default()
} else {
EditorPropertyState.Undefined
}
},
updates = vision.properties.changes,
rootDescriptor = vision.descriptor
)
}
vision.styles.takeIf { it.isNotEmpty() }?.let { styles ->
P {
B { Text("Styles: ") }
Text(styles.joinToString(separator = ", "))
}
}
}
}
}
}
FlexColumn({
style {
paddingAll(4.px)
minWidth(400.px)
height(100.percent)
overflowY("auto")
flex(1, 10, 300.px)
}
}) {
ThreeControls(solid, optionsWithSelector, selected, onSelect = { selected = it }, tabBuilder = tabBuilder)
}
}

View File

@ -1,16 +1,16 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import org.jetbrains.compose.web.ExperimentalComposeWebApi
import org.jetbrains.compose.web.css.*
@OptIn(ExperimentalComposeWebApi::class)
public object TreeStyles : StyleSheet(VisionForgeStyles) {
public object TreeStyles : StyleSheet() {
/**
* Remove default bullets
*/
public val tree: String by style {
paddingLeft(10.px)
paddingLeft(5.px)
marginLeft(0.px)
listStyleType("none")
}
@ -22,7 +22,7 @@ public object TreeStyles : StyleSheet(VisionForgeStyles) {
cursor("pointer")
userSelect(UserSelect.none)
/* Create the caret/arrow with a unicode, and style it */
(self + before) {
before {
content("\u25B6")
color(Color.black)
display(DisplayStyle.InlineBlock)
@ -34,7 +34,7 @@ public object TreeStyles : StyleSheet(VisionForgeStyles) {
* Rotate the caret/arrow icon when clicked on (using JavaScript)
*/
public val treeCaretDown: String by style {
(self + before) {
before {
content("\u25B6")
color(Color.black)
display(DisplayStyle.InlineBlock)
@ -46,11 +46,13 @@ public object TreeStyles : StyleSheet(VisionForgeStyles) {
public val treeItem: String by style {
alignItems(AlignItems.Center)
paddingLeft(10.px)
property("border-left", CSSBorder().apply{
border {
left {
width(1.px)
color(Color.lightgray)
style = LineStyle.Dashed
})
}
}
}
public val treeLabel: String by style {
@ -67,4 +69,26 @@ public object TreeStyles : StyleSheet(VisionForgeStyles) {
public val treeLabelSelected: String by style {
backgroundColor(Color.lightblue)
}
public val propertyEditorButton: String by style {
width(24.px)
alignSelf(AlignSelf.Stretch)
marginAll(1.px, 5.px)
backgroundColor(Color.white)
border{
style(LineStyle.Solid)
}
borderRadius(2.px)
textAlign("center")
textDecoration("none")
cursor("pointer")
disabled {
cursor("auto")
border{
style(LineStyle.Dashed)
}
color(Color.lightgray)
}
}
}

View File

@ -1,9 +1,10 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import org.jetbrains.compose.web.css.Color
import org.jetbrains.compose.web.css.color
import org.jetbrains.compose.web.css.cursor
import org.jetbrains.compose.web.css.textDecorationLine
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text
@ -14,6 +15,8 @@ import space.kscience.dataforge.names.startsWith
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionGroup
import space.kscience.visionforge.asSequence
import space.kscience.visionforge.compose.TreeStyles.hover
import space.kscience.visionforge.compose.TreeStyles.invoke
import space.kscience.visionforge.isEmpty
@ -32,6 +35,10 @@ private fun TreeLabel(
style {
color(Color("#069"))
cursor("pointer")
hover.invoke {
textDecorationLine("underline")
}
}
onClick { clickCallback(name) }
}) {

View File

@ -1,4 +1,4 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.dom.H5

View File

@ -1,4 +1,4 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.keywords.CSSAutoKeyword

View File

@ -1,4 +1,4 @@
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.css.DisplayStyle

View File

@ -1,18 +1,26 @@
@file:Suppress("UNUSED_PARAMETER")
package space.kscience.visionforge.html
package space.kscience.visionforge.compose
import androidx.compose.runtime.*
import com.benasher44.uuid.uuid4
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.css.percent
import org.jetbrains.compose.web.css.px
import org.jetbrains.compose.web.css.width
import org.jetbrains.compose.web.dom.Input
import org.jetbrains.compose.web.dom.Option
import org.jetbrains.compose.web.dom.Select
import org.jetbrains.compose.web.dom.Text
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLOptionElement
import org.w3c.dom.asList
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.descriptors.allowedValues
import space.kscience.visionforge.Colors
import space.kscience.visionforge.widgetType
import three.math.Color
@Composable
@ -22,16 +30,20 @@ public fun StringValueChooser(
value: Value?,
onValueChange: (Value?) -> Unit,
) {
var stringValue by remember(value, descriptor) { mutableStateOf(value?.string ?: "") }
var stringValue by remember { mutableStateOf(value?.string ?: "") }
Input(type = InputType.Text) {
classes("w-100")
value(stringValue)
onChange { event ->
stringValue = event.value
style {
width(100.percent)
}
onInput { event ->
stringValue = event.value
onValueChange(event.value.asValue())
value(stringValue)
onKeyDown { event ->
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
stringValue = (event.target as HTMLInputElement).value
onValueChange(stringValue.asValue())
}
}
onChange {
stringValue = it.target.value
}
}
}
@ -44,29 +56,16 @@ public fun BooleanValueChooser(
value: Value?,
onValueChange: (Value?) -> Unit,
) {
val uid = remember { "checkbox[${uuid4()}]" }
var innerValue by remember(value, descriptor) {
mutableStateOf(
value?.boolean ?: descriptor?.defaultValue?.boolean
)
}
Input(type = InputType.Checkbox) {
classes("btn-check")
checked(innerValue ?: false)
autoComplete(AutoComplete.off)
id(uid)
style {
width(100.percent)
}
//this.attributes["indeterminate"] = (props.item == null).toString()
checked(value?.boolean ?: false)
onInput { event ->
innerValue = event.value
onValueChange(event.value.asValue())
}
}
Label(uid, attrs = { classes("btn", "btn-sm", "btn-outline-secondary", "w-100") }) {
if (innerValue == true) {
Text("On")
} else {
Text("Off")
onChange {
val newValue = it.target.checked
onValueChange(newValue.asValue())
}
}
}
@ -78,18 +77,25 @@ public fun NumberValueChooser(
value: Value?,
onValueChange: (Value?) -> Unit,
) {
var innerValue by remember(value, descriptor) { mutableStateOf(value?.number ?: descriptor?.defaultValue?.number) }
var innerValue by remember { mutableStateOf(value?.string ?: "") }
Input(type = InputType.Number) {
classes("w-100")
value(innerValue ?: descriptor?.defaultValue?.number ?: 0.0)
onChange { event ->
innerValue = event.value
style {
width(100.percent)
}
onInput { event ->
innerValue = event.value
onValueChange(event.value?.asValue())
value(innerValue)
onKeyDown { event ->
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
innerValue = (event.target as HTMLInputElement).value
val number = innerValue.toDoubleOrNull()
if (number == null) {
console.error("The input value $innerValue is not a number")
} else {
onValueChange(number.asValue())
}
}
}
onChange {
innerValue = it.target.value
}
descriptor?.attributes?.get("step").number?.let {
step(it)
@ -111,10 +117,11 @@ public fun ComboValueChooser(
value: Value?,
onValueChange: (Value?) -> Unit,
) {
var selected by remember(value, descriptor) { mutableStateOf(value?.string ?: "") }
var selected by remember { mutableStateOf(value?.string ?: "") }
Select({
classes("w-100")
style {
width(100.percent)
}
onChange {
selected = it.target.value
onValueChange(selected.asValue())
@ -136,24 +143,19 @@ public fun ColorValueChooser(
value: Value?,
onValueChange: (Value?) -> Unit,
) {
var innerValue by remember { mutableStateOf<String?>(value?.string ?: descriptor?.defaultValue?.string) }
Input(type = InputType.Color) {
classes("w-100")
style {
width(100.percent)
marginAll(0.px)
}
value(
value?.let { value ->
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
else value.string
//else "#" + Color(value.string).getHexString()
else "#" + Color(value.string).getHexString()
} ?: "#000000"
)
onChange { event ->
innerValue = event.value
}
onInput { event ->
innerValue = event.value
onValueChange(event.value.asValue())
onChange {
onValueChange(it.target.value.asValue())
}
}
}
@ -167,7 +169,6 @@ public fun MultiSelectChooser(
onValueChange: (Value?) -> Unit,
) {
Select({
classes("w-100","form-select")
onChange { event ->
val newSelected = event.target.selectedOptions.asList()
.map { (it as HTMLOptionElement).value.asValue() }
@ -193,18 +194,40 @@ public fun RangeValueChooser(
value: Value?,
onValueChange: (Value?) -> Unit,
) {
var innerValue by remember(value, descriptor) { mutableStateOf(value?.number ?: descriptor?.defaultValue?.number) }
var innerValue by remember { mutableStateOf(value?.double) }
var rangeDisabled: Boolean by remember { mutableStateOf(state != EditorPropertyState.Defined) }
FlexRow {
if (descriptor?.valueRequirement != ValueRequirement.REQUIRED) {
Input(type = InputType.Checkbox) {
if (!rangeDisabled) defaultChecked()
onChange {
val checkBoxValue = it.target.checked
rangeDisabled = !checkBoxValue
onValueChange(
if (!checkBoxValue) {
null
} else {
innerValue?.asValue()
}
)
}
}
}
}
Input(type = InputType.Range) {
classes("w-100", "form-range")
value(innerValue?.toString() ?: "")
onInput { event ->
innerValue = event.value
style {
width(100.percent)
}
onChange { event ->
innerValue = event.value
onValueChange(innerValue?.asValue())
if (rangeDisabled) disabled()
value(innerValue?.toString() ?: "")
onChange {
val newValue = it.target.value
onValueChange(newValue.toDoubleOrNull()?.asValue())
innerValue = newValue.toDoubleOrNull()
}
descriptor?.attributes?.get("min").string?.let {
min(it)

4
ui/react/README.md Normal file
View File

@ -0,0 +1,4 @@
# Module react

16
ui/react/build.gradle.kts Normal file
View File

@ -0,0 +1,16 @@
plugins {
id("space.kscience.gradle.mpp")
}
kscience {
js()
jsMain {
dependencies {
api(projects.visionforgeSolid)
api("org.jetbrains.kotlin-wrappers:kotlin-styled")
api("org.jetbrains.kotlin-wrappers:kotlin-react-dom")
// implementation(npm("react-select","4.3.0"))
api(projects.visionforgeThreejs)
}
}
}

View File

@ -0,0 +1,149 @@
package space.kscience.visionforge.react
import kotlinx.css.Align
import kotlinx.css.alignItems
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.a
import react.dom.attrs
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.lastOrNull
import space.kscience.dataforge.names.plus
import styled.css
import styled.styledDiv
import styled.styledSpan
public external interface MetaViewerProps : Props {
/**
* Root meta
*/
public var root: Meta
/**
* The title of root node
*/
public var rootName: String?
/**
* Full path to the displayed node in [root]. Could be empty
*/
public var name: Name
/**
* Root descriptor
*/
public var descriptor: MetaDescriptor?
}
private val MetaViewerItem: FC<MetaViewerProps> = fc("MetaViewerItem") { props ->
metaViewerItem(props)
}
private fun RBuilder.metaViewerItem(props: MetaViewerProps) {
var expanded: Boolean by useState { true }
val item = props.root[props.name]
val descriptorItem: MetaDescriptor? = props.descriptor?.get(props.name)
val actualValue = item?.value ?: descriptorItem?.defaultValue
val actualMeta = item ?: descriptorItem?.defaultNode
val token = props.name.lastOrNull()?.toString() ?: props.rootName ?: ""
val expanderClick: (Event) -> Unit = {
expanded = !expanded
}
flexRow {
css {
alignItems = Align.center
}
if (actualMeta?.isLeaf == false) {
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = expanderClick
}
}
}
styledSpan {
css {
+TreeStyles.treeLabel
if (item == null) {
+TreeStyles.treeLabelInactive
}
}
+token
}
styledDiv {
a {
+actualValue.toString()
}
}
}
if (expanded) {
flexColumn {
css {
+TreeStyles.tree
}
val keys = buildSet {
descriptorItem?.children?.keys?.forEach {
add(NameToken(it))
}
actualMeta!!.items.keys.let { addAll(it) }
}
keys.filter { !it.body.startsWith("@") }.forEach { token ->
styledDiv {
css {
+TreeStyles.treeItem
}
child(MetaViewerItem) {
attrs {
this.key = props.name.toString()
this.root = props.root
this.name = props.name + token
this.descriptor = props.descriptor
}
}
//configEditor(props.root, props.name + token, props.descriptor, props.default)
}
}
}
}
}
@JsExport
public val MetaViewer: FC<MetaViewerProps> = fc("MetaViewer") { props ->
child(MetaViewerItem) {
attrs {
this.key = ""
this.root = props.root
this.name = Name.EMPTY
this.descriptor = props.descriptor
}
}
}
public fun RBuilder.metaViewer(meta: Meta, descriptor: MetaDescriptor? = null, key: Any? = null) {
child(MetaViewer) {
attrs {
this.key = key?.toString() ?: ""
this.root = meta
this.descriptor = descriptor
}
}
}

View File

@ -0,0 +1,38 @@
package space.kscience.visionforge.react
import kotlinx.html.js.onChangeFunction
import org.w3c.dom.HTMLOptionElement
import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.asList
import org.w3c.dom.events.Event
import react.FC
import react.dom.attrs
import react.dom.option
import react.dom.select
import react.fc
import space.kscience.dataforge.meta.asValue
import space.kscience.dataforge.meta.descriptors.allowedValues
import space.kscience.dataforge.meta.string
@JsExport
public val MultiSelectChooser: FC<ValueChooserProps> = fc("MultiSelectChooser") { props ->
val onChange: (Event) -> Unit = { event: Event ->
val newSelected = (event.target as HTMLSelectElement).selectedOptions.asList()
.map { (it as HTMLOptionElement).value.asValue() }
props.onValueChange(newSelected.asValue())
}
select {
attrs {
multiple = true
values = (props.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
onChangeFunction = onChange
}
props.descriptor?.allowedValues?.forEach { optionValue ->
option {
+optionValue.string
}
}
}
}

View File

@ -0,0 +1,278 @@
package space.kscience.visionforge.react
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.css.*
import kotlinx.css.properties.TextDecoration
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.attrs
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.ObservableMutableMeta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.remove
import space.kscience.dataforge.names.*
import space.kscience.visionforge.hidden
import styled.css
import styled.styledButton
import styled.styledDiv
import styled.styledSpan
/**
* The display state of a property
*/
public sealed class EditorPropertyState {
public object Defined : EditorPropertyState()
public class Default(public val source: String = "unknown") : EditorPropertyState()
public object Undefined : EditorPropertyState()
}
public external interface PropertyEditorProps : Props {
/**
* Root config object - always non-null
*/
public var meta: MutableMeta
public var getPropertyState: (Name) -> EditorPropertyState
public var scope: CoroutineScope
public var updates: Flow<Name>
/**
* Full path to the displayed node in [meta]. Could be empty
*/
public var name: Name
/**
* Root descriptor
*/
public var descriptor: MetaDescriptor?
/**
* Initial expanded state
*/
public var expanded: Boolean?
}
private val PropertyEditorItem: FC<PropertyEditorProps> = fc("PropertyEditorItem") { props ->
propertyEditorItem(props)
}
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
var expanded: Boolean by useState { props.expanded ?: true }
val descriptor: MetaDescriptor? = useMemo(props.descriptor, props.name) { props.descriptor?.get(props.name) }
var property: MutableMeta by useState { props.meta.getOrCreate(props.name) }
var editorPropertyState: EditorPropertyState by useState { props.getPropertyState(props.name) }
val keys = useMemo(descriptor) {
buildSet {
descriptor?.children?.filterNot {
it.key.startsWith("@") || it.value.hidden
}?.forEach {
add(NameToken(it.key))
}
//ownProperty?.items?.keys?.filterNot { it.body.startsWith("@") }?.let { addAll(it) }
}
}
val token = props.name.lastOrNull()?.toString() ?: "Properties"
fun update() {
property = props.meta.getOrCreate(props.name)
editorPropertyState = props.getPropertyState(props.name)
}
useEffect(props.meta) {
val job = props.updates.onEach { updatedName ->
if (updatedName == props.name) {
update()
}
}.launchIn(props.scope)
cleanup {
job.cancel()
}
}
val expanderClick: (Event) -> Unit = {
expanded = !expanded
}
val removeClick: (Event) -> Unit = {
props.meta.remove(props.name)
update()
}
flexRow {
css {
alignItems = Align.center
}
if (keys.isNotEmpty()) {
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = expanderClick
}
}
}
styledSpan {
css {
+TreeStyles.treeLabel
if (editorPropertyState != EditorPropertyState.Defined) {
+TreeStyles.treeLabelInactive
}
}
+token
}
if (!props.name.isEmpty() && descriptor?.valueRequirement != ValueRequirement.ABSENT) {
styledDiv {
css {
//+TreeStyles.resizeableInput
width = 160.px
margin = Margin(1.px, 5.px)
}
ValueChooser {
attrs {
this.descriptor = descriptor
this.state = editorPropertyState
this.value = property.value
this.onValueChange = {
property.value = it
editorPropertyState = props.getPropertyState(props.name)
}
}
}
}
styledButton {
css {
width = 24.px
alignSelf = Align.stretch
margin = Margin(1.px, 5.px)
backgroundColor = Color.white
borderStyle = BorderStyle.solid
borderRadius = 2.px
textAlign = TextAlign.center
textDecoration = TextDecoration.none
cursor = Cursor.pointer
disabled {
cursor = Cursor.auto
borderStyle = BorderStyle.dashed
color = Color.lightGray
}
}
+"\u00D7"
attrs {
if (editorPropertyState!= EditorPropertyState.Defined) {
disabled = true
} else {
onClickFunction = removeClick
}
}
}
}
}
if (expanded) {
flexColumn {
css {
+TreeStyles.tree
}
keys.forEach { token ->
styledDiv {
css {
+TreeStyles.treeItem
}
child(PropertyEditorItem) {
attrs {
this.key = props.name.toString()
this.meta = props.meta
this.name = props.name + token
this.descriptor = props.descriptor
this.scope = props.scope
this.getPropertyState = { props.getPropertyState(props.name + token) }
this.updates = props.updates
}
}
//configEditor(props.root, props.name + token, props.descriptor, props.default)
}
}
}
}
}
@JsExport
public val PropertyEditor: FC<PropertyEditorProps> = fc("PropertyEditor") { props ->
child(PropertyEditorItem) {
attrs {
this.key = ""
this.meta = props.meta
this.name = Name.EMPTY
this.descriptor = props.descriptor
this.expanded = props.expanded
this.scope = props.scope
this.getPropertyState = props.getPropertyState
this.updates = props.updates
}
}
}
@OptIn(ExperimentalCoroutinesApi::class)
public fun RBuilder.propertyEditor(
scope: CoroutineScope,
properties: ObservableMutableMeta,
descriptor: MetaDescriptor? = null,
key: Any? = null,
expanded: Boolean? = null,
) {
child(PropertyEditor) {
attrs {
this.meta = properties
this.descriptor = descriptor
this.key = key?.toString() ?: ""
this.expanded = expanded
this.scope = scope
this.getPropertyState = { name ->
if (properties[name] != null) {
EditorPropertyState.Defined
} else if (descriptor?.get(name)?.defaultValue != null) {
EditorPropertyState.Default("descriptor")
} else {
EditorPropertyState.Undefined
}
}
this.updates = callbackFlow {
properties.onChange(scope) { name ->
scope.launch {
send(name)
}
}
invokeOnClose {
properties.removeListener(scope)
}
}
}
}
}

View File

@ -0,0 +1,78 @@
package space.kscience.visionforge.react
import kotlinx.css.pct
import kotlinx.css.width
import kotlinx.html.InputType
import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onInputFunction
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event
import react.FC
import react.dom.attrs
import react.fc
import react.useState
import space.kscience.dataforge.meta.asValue
import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.double
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.string
import styled.css
import styled.styledInput
@JsExport
public val RangeValueChooser: FC<ValueChooserProps> = fc("RangeValueChooser") { props ->
var innerValue by useState(props.value?.double)
var rangeDisabled: Boolean by useState(props.state != EditorPropertyState.Defined)
val handleDisable: (Event) -> Unit = {
val checkBoxValue = (it.target as HTMLInputElement).checked
rangeDisabled = !checkBoxValue
props.onValueChange(
if (!checkBoxValue) {
null
} else {
innerValue?.asValue()
}
)
}
val handleChange: (Event) -> Unit = {
val newValue = (it.target as HTMLInputElement).value
props.onValueChange(newValue.toDoubleOrNull()?.asValue())
innerValue = newValue.toDoubleOrNull()
}
flexRow {
if (props.descriptor?.valueRequirement != ValueRequirement.REQUIRED) {
styledInput(type = InputType.checkBox) {
attrs {
defaultChecked = rangeDisabled.not()
onChangeFunction = handleDisable
}
}
}
styledInput(type = InputType.range) {
css {
width = 100.pct
}
attrs {
disabled = rangeDisabled
value = innerValue?.toString() ?: ""
// onChangeFunction = handleChange
onInputFunction = handleChange
val minValue = props.descriptor?.attributes?.get("min").string
minValue?.let {
min = it
}
val maxValue = props.descriptor?.attributes?.get("max").string
maxValue?.let {
max = it
}
props.descriptor?.attributes?.get("step").string?.let {
step = it
}
}
}
}
}

View File

@ -0,0 +1,55 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import org.w3c.dom.Element
import react.*
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreeCanvas
import space.kscience.visionforge.solid.three.ThreePlugin
import styled.css
import styled.styledDiv
public external interface ThreeCanvasProps : Props {
public var context: Context
public var options: Canvas3DOptions?
public var solid: Solid?
public var selected: Name?
}
public val ThreeCanvasComponent: FC<ThreeCanvasProps> = fc("ThreeCanvasComponent") { props ->
val elementRef = useRef<Element>(null)
var canvas by useState<ThreeCanvas?>(null)
val three: ThreePlugin = useMemo(props.context) { props.context.request(ThreePlugin) }
useEffect(props.solid, props.options, elementRef) {
if (canvas == null) {
val element = elementRef.current ?: error("Canvas element not found")
canvas = ThreeCanvas(three, element, props.options ?: Canvas3DOptions())
}
}
useEffect(canvas, props.solid) {
props.solid?.let { obj ->
canvas?.render(obj)
}
}
useEffect(canvas, props.selected) {
canvas?.select(props.selected)
}
styledDiv {
css {
maxWidth = 100.vw
maxHeight = 100.vh
width = 100.pct
height = 100.pct
}
ref = elementRef
}
}

View File

@ -0,0 +1,69 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import kotlinx.css.properties.deg
import kotlinx.css.properties.rotate
import styled.StyleSheet
public object TreeStyles : StyleSheet("treeStyles", true) {
/**
* Remove default bullets
*/
public val tree: RuleSet by css {
paddingLeft = 5.px
marginLeft = 0.px
listStyleType = ListStyleType.none
}
/**
* Style the caret/arrow
*/
public val treeCaret: RuleSet by css {
cursor = Cursor.pointer
userSelect = UserSelect.none
/* Create the caret/arrow with a unicode, and style it */
before {
content = "\u25B6".quoted
color = Color.black
display = Display.inlineBlock
marginRight = 6.px
}
}
/**
* Rotate the caret/arrow icon when clicked on (using JavaScript)
*/
public val treeCaredDown:RuleSet by css {
before {
content = "\u25B6".quoted
color = Color.black
display = Display.inlineBlock
marginRight = 6.px
transform.rotate(90.deg)
}
}
public val treeItem:RuleSet by css {
alignItems = Align.center
paddingLeft = 10.px
borderLeftStyle = BorderStyle.dashed
borderLeftWidth = 1.px
borderLeftColor = Color.lightGray
}
public val treeLabel:RuleSet by css {
border = Border.none
padding = Padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt)
textAlign = TextAlign.left
flex = Flex(1.0)
}
public val treeLabelInactive: RuleSet by css {
color = Color.lightGray
}
public val treeLabelSelected:RuleSet by css {
backgroundColor = Color.lightBlue
}
}

View File

@ -0,0 +1,126 @@
package space.kscience.visionforge.react
import kotlinx.css.*
import kotlinx.css.properties.TextDecoration
import kotlinx.css.properties.TextDecorationLine
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.attrs
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.lastOrNull
import space.kscience.dataforge.names.plus
import space.kscience.dataforge.names.startsWith
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionGroup
import space.kscience.visionforge.asSequence
import space.kscience.visionforge.isEmpty
import styled.css
import styled.styledDiv
import styled.styledSpan
public external interface ObjectTreeProps : Props {
public var name: Name
public var selected: Name?
public var obj: Vision
public var clickCallback: (Name) -> Unit
}
private val TreeLabel = fc<ObjectTreeProps> { props ->
val token = useMemo(props.name) { props.name.lastOrNull()?.toString() ?: "World" }
styledSpan {
css {
+TreeStyles.treeLabel
color = Color("#069")
cursor = Cursor.pointer
hover {
textDecoration = TextDecoration(setOf(TextDecorationLine.underline))
}
if (props.name == props.selected) {
+TreeStyles.treeLabelSelected
}
}
+token
attrs {
onClickFunction = { props.clickCallback(props.name) }
}
}
}
private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
var expanded: Boolean by useState { props.selected?.startsWith(props.name) ?: false }
val onClick: (Event) -> Unit = {
expanded = !expanded
}
val obj = props.obj
//display as node if any child is visible
if (obj is VisionGroup) {
flexRow {
if (obj.children.keys.any { !it.body.startsWith("@") }) {
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = onClick
}
}
}
child(TreeLabel, props = props)
}
if (expanded) {
flexColumn {
css {
+TreeStyles.tree
}
obj.children.asSequence()
.filter { !it.first.toString().startsWith("@") } // ignore statics and other hidden children
.sortedBy { (it.second as? VisionGroup)?.children?.isEmpty() ?: true } // ignore empty groups
.forEach { (childToken, child) ->
styledDiv {
css {
+TreeStyles.treeItem
}
child(ObjectTree) {
attrs {
this.name = props.name + childToken
this.obj = child
this.selected = props.selected
this.clickCallback = props.clickCallback
}
}
}
}
}
}
} else {
child(TreeLabel, props = props)
}
}
@JsExport
public val ObjectTree: FC<ObjectTreeProps> = fc("ObjectTree") { props ->
visionTree(props)
}
public fun RBuilder.visionTree(
vision: Vision,
selected: Name? = null,
clickCallback: (Name) -> Unit = {},
) {
child(ObjectTree) {
attrs {
this.name = Name.EMPTY
this.obj = vision
this.selected = selected
this.clickCallback = clickCallback
}
}
}

View File

@ -0,0 +1,17 @@
@file:JsModule("react-dom/client")
@file:JsNonModule
package space.kscience.visionforge.react
import org.w3c.dom.Element
import react.dom.client.Root
import react.dom.client.RootOptions
/**
* Compatibility method to work with old browser API
*/
public external fun createRoot(
container: Element,
options: RootOptions = definedExternally,
): Root

View File

@ -0,0 +1,10 @@
package space.kscience.visionforge.react
import react.Props
import react.RBuilder
import react.createElement
import react.dom.client.Root
public fun Root.render(block: RBuilder.() -> Unit) {
render(createElement<Props>(block))
}

View File

@ -0,0 +1,31 @@
package space.kscience.visionforge.react
import kotlinx.css.Display
import kotlinx.css.FlexDirection
import kotlinx.css.display
import kotlinx.css.flexDirection
import kotlinx.html.DIV
import react.RBuilder
import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
public inline fun RBuilder.flexColumn(
block: StyledDOMBuilder<DIV>.() -> Unit
): Unit = styledDiv {
css {
display = Display.flex
flexDirection = FlexDirection.column
}
block()
}
public inline fun RBuilder.flexRow(
block: StyledDOMBuilder<DIV>.() -> Unit
): Unit = styledDiv {
css {
display = Display.flex
flexDirection = FlexDirection.row
}
block()
}

Some files were not shown because too many files have changed in this diff Show More