Compare commits
No commits in common. "fd5ff5e30ca7ff2d1f8914ce58063638ae5bc267" and "6ce1e68b866ad56fb18aa5299b372108f4d32caf" have entirely different histories.
fd5ff5e30c
...
6ce1e68b86
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,10 +3,8 @@
|
||||
*.iws
|
||||
out/
|
||||
.gradle
|
||||
.kotlin
|
||||
build/
|
||||
data/
|
||||
.kotlin/
|
||||
|
||||
!gradle-wrapper.jar
|
||||
|
||||
|
4
.space.kts
Normal file
4
.space.kts
Normal file
@ -0,0 +1,4 @@
|
||||
job("Build") {
|
||||
gradlew("openjdk:11", "build")
|
||||
}
|
||||
|
65
CHANGELOG.md
65
CHANGELOG.md
@ -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
|
||||
|
||||
|
160
README.md
160
README.md
@ -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)
|
||||
>
|
||||
> **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)
|
||||
* ### [visionforge-fx](visionforge-fx)
|
||||
>
|
||||
>
|
||||
> **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.
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -1,4 +0,0 @@
|
||||
# Module compose-desktop-demo
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
commonWebpackConfig {
|
||||
cssSupport {
|
||||
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"
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
50
demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt
Normal file
50
demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt
Normal 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
|
||||
}
|
@ -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();
|
||||
//});
|
@ -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,38 +57,43 @@ 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")
|
||||
}
|
||||
FileDrop("(drag file here)") { files ->
|
||||
val file = files[0]
|
||||
if (file != null) {
|
||||
readFileAsync(file)
|
||||
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?.get(0)
|
||||
if (file != null) {
|
||||
deferredVision = readFileAsync(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 {
|
||||
|
||||
val context = Context("gdml-demo") {
|
||||
plugin(ThreePlugin)
|
||||
}
|
||||
|
||||
override fun start(document: Document, state: Map<String, Any>) {
|
||||
val context = Context("gdml-demo"){
|
||||
plugin(ThreePlugin)
|
||||
}
|
||||
|
||||
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
|
||||
injectGlobal {
|
||||
html{
|
||||
height = 100.pct
|
||||
}
|
||||
|
||||
val vision = GdmlShowCase.cubes().toVision().apply {
|
||||
ambientLight {
|
||||
color(Colors.white)
|
||||
body{
|
||||
height = 100.pct
|
||||
display = Display.flex
|
||||
alignItems = Align.stretch
|
||||
}
|
||||
|
||||
"#application"{
|
||||
width = 100.pct
|
||||
display = Display.flex
|
||||
alignItems = Align.stretch
|
||||
}
|
||||
}
|
||||
|
||||
renderComposable(element) {
|
||||
Style(VisionForgeStyles)
|
||||
Style {
|
||||
"html" {
|
||||
height(100.percent)
|
||||
}
|
||||
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
|
||||
|
||||
"body" {
|
||||
height(100.percent)
|
||||
display(DisplayStyle.Flex)
|
||||
alignItems(AlignItems.Stretch)
|
||||
createRoot(element).render {
|
||||
child(GDMLApp) {
|
||||
val vision = GdmlShowCase.cubes().toVision().apply {
|
||||
ambientLight {
|
||||
color(Colors.white)
|
||||
}
|
||||
}
|
||||
|
||||
"#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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
3
demo/gdml/webpack.config.d/01.ring.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
|
||||
|
||||
config.module.rules.push(...ringConfig.module.rules)
|
@ -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
|
||||
commonWebpackConfig {
|
||||
cssSupport {
|
||||
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)
|
||||
}
|
||||
}
|
@ -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,34 +66,43 @@ private class JsPlaygroundApp : Application {
|
||||
// }
|
||||
// }
|
||||
Tab("spheres") {
|
||||
Div({
|
||||
style {
|
||||
height(100.vh - 50.pt)
|
||||
styledDiv {
|
||||
css {
|
||||
height = 100.vh - 50.pt
|
||||
}
|
||||
}) {
|
||||
ThreeView(playgroundContext, SolidGroup {
|
||||
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)
|
||||
material {
|
||||
color(Random.nextInt())
|
||||
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)
|
||||
material {
|
||||
color(random.nextInt())
|
||||
}
|
||||
detail = 16
|
||||
}
|
||||
}
|
||||
detail = 16
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Tab("plotly") {
|
||||
Plot(playgroundContext) {
|
||||
scatter {
|
||||
x(1, 2, 3)
|
||||
y(5, 8, 7)
|
||||
Plotly {
|
||||
attrs {
|
||||
plot = space.kscience.plotly.Plotly.plot {
|
||||
scatter {
|
||||
x(1, 2, 3)
|
||||
y(5, 8, 7)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,7 +110,6 @@ private class JsPlaygroundApp : Application {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public fun main() {
|
||||
|
@ -1,163 +1,110 @@
|
||||
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 {
|
||||
name = "velocity"
|
||||
}
|
||||
val GravityDemo = fc<DemoProps> { props ->
|
||||
val velocityTrace = Trace {
|
||||
name = "velocity"
|
||||
}
|
||||
|
||||
val energyTrace = remember {
|
||||
Trace {
|
||||
name = "energy"
|
||||
}
|
||||
val energyTrace = Trace {
|
||||
name = "energy"
|
||||
}
|
||||
val markup = VisionOfMarkup()
|
||||
|
||||
val markup = remember { VisionOfMarkup() }
|
||||
|
||||
val solid = remember {
|
||||
SolidGroup {
|
||||
pointLight(200, 200, 200, name = "light") {
|
||||
color(Colors.white)
|
||||
}
|
||||
ambientLight()
|
||||
|
||||
sphere(5.0, "ball") {
|
||||
detail = 16
|
||||
color("red")
|
||||
y = h
|
||||
|
||||
|
||||
box(200, 5, 200, name = "floor") {
|
||||
y = -2.5
|
||||
}
|
||||
}
|
||||
styledDiv {
|
||||
css {
|
||||
height = 100.vh - 50.pt
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(solid) {
|
||||
val ball = solid["ball"]!!
|
||||
val g = 10.0
|
||||
val dt = 0.1
|
||||
var time = 0.0
|
||||
var velocity = 0.0
|
||||
while (isActive) {
|
||||
delay(20)
|
||||
time += dt
|
||||
velocity -= g * dt
|
||||
val energy = g * ball.y.toDouble() + velocity * velocity / 2
|
||||
ball.y = ball.y.toDouble() + velocity * dt
|
||||
|
||||
velocityTrace.appendXYLatest(time, ball.y)
|
||||
energyTrace.appendXYLatest(time, energy)
|
||||
|
||||
if (ball.y.toDouble() <= 2.5) {
|
||||
//conservation of energy
|
||||
velocity = sqrt(2 * g * h)
|
||||
styledDiv {
|
||||
css {
|
||||
height = 50.vh
|
||||
}
|
||||
child(ThreeCanvasWithControls) {
|
||||
attrs {
|
||||
solids = props.solids
|
||||
solid {
|
||||
pointLight(200, 200, 200, name = "light"){
|
||||
color(Colors.white)
|
||||
}
|
||||
ambientLight()
|
||||
|
||||
markup.content = """
|
||||
## Bouncing sphere parameters
|
||||
|
||||
**velocity** = $velocity
|
||||
|
||||
**energy** = $energy
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
sphere(5.0, "ball") {
|
||||
detail = 16
|
||||
color("red")
|
||||
val h = 100.0
|
||||
y = h
|
||||
solids.context.launch {
|
||||
val g = 10.0
|
||||
val dt = 0.1
|
||||
var time = 0.0
|
||||
var velocity = 0.0
|
||||
while (isActive) {
|
||||
delay(20)
|
||||
time += dt
|
||||
velocity -= g * dt
|
||||
val energy = g * y.toDouble() + velocity * velocity / 2
|
||||
y = y.toDouble() + velocity * dt
|
||||
|
||||
Div({
|
||||
style {
|
||||
height(100.vh - 50.pt)
|
||||
}
|
||||
}) {
|
||||
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) {
|
||||
traces(velocityTrace, energyTrace)
|
||||
layout {
|
||||
xaxis.title = "time"
|
||||
velocityTrace.appendXYLatest(time, y)
|
||||
energyTrace.appendXYLatest(time, energy)
|
||||
|
||||
if (y.toDouble() <= 2.5) {
|
||||
//conservation of energy
|
||||
velocity = sqrt(2 * g * h)
|
||||
}
|
||||
|
||||
markup.content = """
|
||||
## Bouncing sphere parameters
|
||||
|
||||
**velocity** = $velocity
|
||||
|
||||
**energy** = $energy
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
box(200, 5, 200, name = "floor") {
|
||||
y = -2.5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
flexRow {
|
||||
css {
|
||||
alignContent = Align.stretch
|
||||
alignItems = Align.stretch
|
||||
height = 50.vh - 50.pt
|
||||
}
|
||||
plotly {
|
||||
traces(velocityTrace, energyTrace)
|
||||
layout {
|
||||
xaxis.title = "time"
|
||||
}
|
||||
}
|
||||
Markup {
|
||||
attrs {
|
||||
this.markup = markup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
55
demo/js-playground/src/jsMain/kotlin/markupComponent.kt
Normal file
55
demo/js-playground/src/jsMain/kotlin/markupComponent.kt
Normal 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
|
||||
}
|
||||
}
|
43
demo/js-playground/src/jsMain/kotlin/plotlyComponent.kt
Normal file
43
demo/js-playground/src/jsMain/kotlin/plotlyComponent.kt
Normal 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)
|
||||
}
|
||||
}
|
3
demo/js-playground/webpack.config.d/01.ring.js
vendored
Normal file
3
demo/js-playground/webpack.config.d/01.ring.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
|
||||
|
||||
config.module.rules.push(...ringConfig.module.rules)
|
@ -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;
|
||||
|
@ -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")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -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()
|
||||
}
|
||||
|
@ -1,113 +1,281 @@
|
||||
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 {
|
||||
ambientLight{
|
||||
color(Colors.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
val event = window.fetch(
|
||||
"http://localhost:8080/event",
|
||||
RequestInit("GET")
|
||||
).then { response ->
|
||||
if (response.ok) {
|
||||
response.text()
|
||||
} else {
|
||||
error("Failed to get event")
|
||||
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")
|
||||
).then { response ->
|
||||
if (response.ok) {
|
||||
response.text()
|
||||
} else {
|
||||
error("Failed to get event")
|
||||
}
|
||||
}.then { body ->
|
||||
Json.decodeFromString(Event.serializer(), body)
|
||||
}.await()
|
||||
events = events + event
|
||||
props.model.displayEvent(event)
|
||||
}
|
||||
}
|
||||
}.then { body ->
|
||||
Json.decodeFromString(Event.serializer(), body)
|
||||
}.await()
|
||||
events.add(event)
|
||||
model.displayEvent(event)
|
||||
}
|
||||
}
|
||||
button {
|
||||
+"Clear"
|
||||
attrs {
|
||||
onClickFunction = {
|
||||
events = emptySet()
|
||||
props.model.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Button("Clear", color = bootstrap.Color.Secondary) {
|
||||
events.clear()
|
||||
model.reset()
|
||||
}
|
||||
}
|
||||
|
||||
events.forEach { event ->
|
||||
P {
|
||||
Span {
|
||||
Text(event.id.toString())
|
||||
p {
|
||||
styledSpan {
|
||||
+event.id.toString()
|
||||
}
|
||||
Text(" : ")
|
||||
Span({
|
||||
style {
|
||||
color(Color.blue)
|
||||
+" : "
|
||||
styledSpan {
|
||||
css {
|
||||
color = Color.blue
|
||||
}
|
||||
}) {
|
||||
Text(event.hits.toString())
|
||||
+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)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
3
demo/muon-monitor/webpack.config.d/01.ring.js
vendored
Normal file
3
demo/muon-monitor/webpack.config.d/01.ring.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
|
||||
|
||||
config.module.rules.push(...ringConfig.module.rules)
|
@ -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
|
||||
|
@ -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"))
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
@ -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()
|
||||
}
|
@ -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") {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
23
demo/playground/webpack.config.d/01.ring.js
vendored
Normal file
23
demo/playground/webpack.config.d/01.ring.js
vendored
Normal 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: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -8,16 +8,6 @@ kscience {
|
||||
jvm()
|
||||
js{
|
||||
binaries.executable()
|
||||
browser{
|
||||
commonWebpackConfig{
|
||||
cssSupport{
|
||||
enabled = true
|
||||
}
|
||||
scssSupport{
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation(projects.visionforgeSolid)
|
||||
|
@ -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")
|
||||
@ -114,7 +111,7 @@ fun VisionLayout<Solid>.showcase() {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
while (isActive) {
|
||||
delay(100)
|
||||
rotate((PI / 20).radians, Euclidean3DSpace.yAxis)
|
||||
rotate((PI/20).radians,Euclidean3DSpace.yAxis)
|
||||
}
|
||||
}
|
||||
color(Colors.red)
|
||||
@ -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)
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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.
Binary file not shown.
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
@ -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")
|
@ -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
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
|
||||
|
@ -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
4
ui/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module ui
|
||||
|
||||
|
||||
|
4
ui/bootstrap/README.md
Normal file
4
ui/bootstrap/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module bootstrap
|
||||
|
||||
|
||||
|
19
ui/bootstrap/build.gradle.kts
Normal file
19
ui/bootstrap/build.gradle.kts
Normal 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"))
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
// }
|
||||
//}
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
@ -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)
|
||||
}
|
56
ui/bootstrap/src/jsMain/resources/css/custom-bootstrap.css
Normal file
56
ui/bootstrap/src/jsMain/resources/css/custom-bootstrap.css
Normal 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;
|
||||
}
|
41
ui/compose/build.gradle.kts
Normal file
41
ui/compose/build.gradle.kts
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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) }
|
@ -1,31 +1,26 @@
|
||||
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
|
||||
|
||||
@Composable
|
||||
public fun NameCrumbs(name: Name?, link: (Name) -> Unit): Unit = Nav({
|
||||
attr("aria-label", "breadcrumb")
|
||||
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")
|
||||
}
|
||||
Text("\u2302")
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
@ -33,16 +28,15 @@ public fun NameCrumbs(name: Name?, link: (Name) -> Unit): Unit = Nav({
|
||||
name.tokens.forEach { token ->
|
||||
tokens.add(token)
|
||||
val fullName = Name(tokens.toList())
|
||||
Text(".")
|
||||
Li({
|
||||
classes("breadcrumb-item")
|
||||
if (tokens.size == name.length) classes("active")
|
||||
if(tokens.size == name.length) classes("active")
|
||||
onClick {
|
||||
link(fullName)
|
||||
}
|
||||
}) {
|
||||
A("#") {
|
||||
Text(token.toString())
|
||||
}
|
||||
Text(token.toString())
|
||||
}
|
||||
}
|
||||
}
|
@ -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 -> {
|
||||
classes(TreeStyles.treeLabelInactive)
|
||||
}
|
||||
|
||||
EditorPropertyState.Defined -> {}
|
||||
if (editorPropertyState != EditorPropertyState.Defined) {
|
||||
classes(TreeStyles.treeLabelInactive)
|
||||
}
|
||||
}) {
|
||||
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")
|
||||
onClick {
|
||||
rootMeta.remove(name)
|
||||
update()
|
||||
|
||||
Button({
|
||||
classes(TreeStyles.propertyEditorButton)
|
||||
if (editorPropertyState != EditorPropertyState.Defined) {
|
||||
disabled()
|
||||
} else {
|
||||
onClick {
|
||||
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,
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
width(1.px)
|
||||
color(Color.lightgray)
|
||||
style = LineStyle.Dashed
|
||||
})
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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) }
|
||||
}) {
|
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
||||
|
||||
onInput { event ->
|
||||
innerValue = event.value
|
||||
onValueChange(event.value.asValue())
|
||||
style {
|
||||
width(100.percent)
|
||||
}
|
||||
}
|
||||
Label(uid, attrs = { classes("btn", "btn-sm", "btn-outline-secondary", "w-100") }) {
|
||||
if (innerValue == true) {
|
||||
Text("On")
|
||||
} else {
|
||||
Text("Off")
|
||||
//this.attributes["indeterminate"] = (props.item == null).toString()
|
||||
checked(value?.boolean ?: false)
|
||||
|
||||
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
4
ui/react/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module react
|
||||
|
||||
|
||||
|
16
ui/react/build.gradle.kts
Normal file
16
ui/react/build.gradle.kts
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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))
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user