Semántico sayk'uy · 30
bindings/kotlin/stretch/src/main/rust/src/lib.rs
46 qillqakuna · +523 −382
diff --git a/.circleci/config.yml b/.circleci/config.yml
index cf5487e91..0e5050e4f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,7 +1,7 @@
version: 2
jobs:
- build:
+ core:
docker:
- image: rust:1
@@ -23,4 +23,100 @@ jobs:
key: target-cache
paths:
- ~/.cargo
- - ./target
\ No newline at end of file
+ - ./target
+
+ android:
+ docker:
+ - image: circleci/android:api-28
+
+ environment:
+ _JAVA_OPTIONS: "-Xmx3200m -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:ParallelGCThreads=2 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 -Djava.util.concurrent.ForkJoinPool.common.parallelism=2"
+
+ steps:
+ - checkout
+ - restore_cache:
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "stretch/build.gradle" }}
+ - run: yes | sdkmanager --update || true
+ - run: cd android && ./gradlew androidDependencies --no-daemon --max-workers 2
+ - save_cache:
+ paths:
+ - ~/.gradle
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "stretch/build.gradle" }}
+ - run:
+ name: Setup emulator
+ command: sdkmanager "system-images;android-16;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-16;default;armeabi-v7a"
+ - run:
+ name: Launch emulator
+ command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel auto -verbose
+ background: true
+ - run:
+ name: Wait emulator
+ command: |
+ # wait for it to have booted
+ circle-android wait-for-boot
+ # unlock the emulator screen
+ sleep 30
+ adb shell input keyevent 82
+ - run:
+ name: Run tests
+ command: ./gradlew connectedAndroidTest
+ - store_artifacts:
+ path: stretch/build/reports
+ destination: reports
+ - store_test_results:
+ path: stretch/build/test-results
+
+workflows:
+ version: 2
+ test_all:
+ jobs:
+ - android
+ - core
+
+
+version: 2
+jobs:
+ build:
+ working_directory: ~/code
+ docker:
+ # Android the primary container
+ - image: circleci/android:api-26-alpha
+ environment:
+ JVM_OPTS: -Xmx3200m
+ steps:
+ - checkout
+ - restore_cache:
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
+ - run:
+ name: Download Dependencies
+ command: ./gradlew androidDependencies
+ - save_cache:
+ paths:
+ - ~/.gradle
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
+ - run:
+ name: Run UnitTest
+ command: ./gradlew testDemoDebugUnitTest
+ - run:
+ name: Setup emulator
+ command: sdkmanager "system-images;android-16;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-16;default;armeabi-v7a"
+ - run:
+ name: Launch emulator
+ command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel auto -verbose
+ background: true
+ - run:
+ name: Wait emulator
+ command: |
+ # wait for it to have booted
+ circle-android wait-for-boot
+ # unlock the emulator screen
+ sleep 30
+ adb shell input keyevent 82
+ - run:
+ name: Run EspressoTests
+ command: ./gradlew connectedDemoDebugAndroidTest
+ - store_artifacts:
+ path: app/build/reports
+ destination: reports
+ - store_test_results:
+ path: app/build/test-results
diff --git a/Cargo.toml b/Cargo.toml
index 7041f4984..abdddc80e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "stretch"
-version = "0.2.1"
+version = "0.2.2"
authors = ["Emil Sjölander <emil@visly.app>"]
edition = "2018"
include = ["src/**/*", "Cargo.toml"]
diff --git a/bindings/kotlin/.idea/codeStyles/Project.xml b/bindings/kotlin/.idea/codeStyles/Project.xml
index 34dc27cb6..1bec35e57 100644
--- a/bindings/kotlin/.idea/codeStyles/Project.xml
+++ b/bindings/kotlin/.idea/codeStyles/Project.xml
@@ -3,31 +3,6 @@
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
- <Objective-C-extensions>
- <file>
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
- </file>
- <class>
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
- </class>
- <extensions>
- <pair source="cpp" header="h" fileNamingConvention="NONE" />
- <pair source="c" header="h" fileNamingConvention="NONE" />
- </extensions>
- </Objective-C-extensions>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
diff --git a/bindings/kotlin/.idea/encodings.xml b/bindings/kotlin/.idea/encodings.xml
new file mode 100644
index 000000000..15a15b218
--- /dev/null
+++ b/bindings/kotlin/.idea/encodings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project>
\ No newline at end of file
diff --git a/bindings/kotlin/.idea/gradle.xml b/bindings/kotlin/.idea/gradle.xml
index 5f07c20d7..8ec153ca0 100644
--- a/bindings/kotlin/.idea/gradle.xml
+++ b/bindings/kotlin/.idea/gradle.xml
@@ -8,7 +8,6 @@
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
- <option value="$PROJECT_DIR$/sample" />
<option value="$PROJECT_DIR$/stretch" />
</set>
</option>
diff --git a/bindings/kotlin/build.gradle b/bindings/kotlin/build.gradle
index a6b2983d1..af2e4069c 100644
--- a/bindings/kotlin/build.gradle
+++ b/bindings/kotlin/build.gradle
@@ -8,7 +8,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.2'
+ classpath 'com.android.tools.build:gradle:3.4.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/bindings/kotlin/gradle/wrapper/gradle-wrapper.properties b/bindings/kotlin/gradle/wrapper/gradle-wrapper.properties
index 253fb2e29..3e48a3deb 100644
--- a/bindings/kotlin/gradle/wrapper/gradle-wrapper.properties
+++ b/bindings/kotlin/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Apr 08 13:50:07 BST 2019
+#Tue Apr 23 11:26:41 BST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/bindings/kotlin/sample/.gitignore b/bindings/kotlin/sample/.gitignore
deleted file mode 100644
index 796b96d1c..000000000
--- a/bindings/kotlin/sample/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
diff --git a/bindings/kotlin/sample/build.gradle b/bindings/kotlin/sample/build.gradle
deleted file mode 100644
index 4881844e0..000000000
--- a/bindings/kotlin/sample/build.gradle
+++ /dev/null
@@ -1,35 +0,0 @@
-apply plugin: 'com.android.application'
-
-apply plugin: 'kotlin-android'
-
-apply plugin: 'kotlin-android-extensions'
-
-android {
- compileSdkVersion 28
- defaultConfig {
- applicationId "app.visly.stretch.sample"
- minSdkVersion 15
- targetSdkVersion 28
- versionCode 1
- versionName "1.0"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
-}
-
-dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation 'com.android.support:appcompat-v7:28.0.0'
- implementation 'com.android.support.constraint:constraint-layout:1.1.3'
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'com.android.support.test:runner:1.0.2'
- androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
- implementation project(path: ':stretch')
-}
diff --git a/bindings/kotlin/sample/proguard-rules.pro b/bindings/kotlin/sample/proguard-rules.pro
deleted file mode 100644
index f1b424510..000000000
--- a/bindings/kotlin/sample/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
diff --git a/bindings/kotlin/sample/src/main/AndroidManifest.xml b/bindings/kotlin/sample/src/main/AndroidManifest.xml
deleted file mode 100644
index b9bdbe240..000000000
--- a/bindings/kotlin/sample/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="app.visly.stretch.sample">
-
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/AppTheme">
- <activity android:name=".MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
-
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
\ No newline at end of file
diff --git a/bindings/kotlin/sample/src/main/java/app/visly/stretch/sample/MainActivity.kt b/bindings/kotlin/sample/src/main/java/app/visly/stretch/sample/MainActivity.kt
deleted file mode 100644
index 9ca654433..000000000
--- a/bindings/kotlin/sample/src/main/java/app/visly/stretch/sample/MainActivity.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package app.visly.stretch.sample
-
-import android.support.v7.app.AppCompatActivity
-import android.os.Bundle
-import android.util.Log
-import app.visly.stretch.*
-
-class MainActivity : AppCompatActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
-
- val child1 = Node(Style(size = Size(Dimension.Points(100f), Dimension.Points(100f))), listOf())
- val child2 = Node(Style(size = Size(Dimension.Points(100f), Dimension.Points(100f))), listOf())
- val child3 = Node(Style(size = Size(Dimension.Points(100f), Dimension.Points(100f))), listOf())
-
- val node = Node(
- Style(
- flexDirection = FlexDirection.Column,
- size = Size(
- width = Dimension.Points(100f),
- height = Dimension.Undefined
- )
- ),
- listOf(child1, child2, child3)
- )
-
- val layout = node.computeLayout(Size(null, null))
-
- Log.d("visly-debug-log", "" + layout)
- }
-}
diff --git a/bindings/kotlin/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/bindings/kotlin/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 6348baae3..000000000
--- a/bindings/kotlin/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt"
- android:width="108dp"
- android:height="108dp"
- android:viewportHeight="108"
- android:viewportWidth="108">
- <path
- android:fillType="evenOdd"
- android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
- android:strokeColor="#00000000"
- android:strokeWidth="1">
- <aapt:attr name="android:fillColor">
- <gradient
- android:endX="78.5885"
- android:endY="90.9159"
- android:startX="48.7653"
- android:startY="61.0927"
- android:type="linear">
- <item
- android:color="#44000000"
- android:offset="0.0"/>
- <item
- android:color="#00000000"
- android:offset="1.0"/>
- </gradient>
- </aapt:attr>
- </path>
- <path
- android:fillColor="#FFFFFF"
- android:fillType="nonZero"
- android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
- android:strokeColor="#00000000"
- android:strokeWidth="1"/>
-</vector>
diff --git a/bindings/kotlin/sample/src/main/res/drawable/ic_launcher_background.xml b/bindings/kotlin/sample/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index a0ad202f9..000000000
--- a/bindings/kotlin/sample/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="108dp"
- android:width="108dp"
- android:viewportHeight="108"
- android:viewportWidth="108">
- <path android:fillColor="#008577"
- android:pathData="M0,0h108v108h-108z"/>
- <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
-</vector>
diff --git a/bindings/kotlin/sample/src/main/res/layout/activity_main.xml b/bindings/kotlin/sample/src/main/res/layout/activity_main.xml
deleted file mode 100644
index b87aade91..000000000
--- a/bindings/kotlin/sample/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".sample.MainActivity">
-
- <TextView
- android:id="@+id/sample_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello World!"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent"/>
-
-</android.support.constraint.ConstraintLayout>
\ No newline at end of file
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/bindings/kotlin/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index bbd3e0212..000000000
--- a/bindings/kotlin/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@drawable/ic_launcher_background"/>
- <foreground android:drawable="@drawable/ic_launcher_foreground"/>
-</adaptive-icon>
\ No newline at end of file
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/bindings/kotlin/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index bbd3e0212..000000000
--- a/bindings/kotlin/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@drawable/ic_launcher_background"/>
- <foreground android:drawable="@drawable/ic_launcher_foreground"/>
-</adaptive-icon>
\ No newline at end of file
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-hdpi/ic_launcher.png b/bindings/kotlin/sample/src/main/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 898f3ed59..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/bindings/kotlin/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png
deleted file mode 100644
index dffca3601..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-mdpi/ic_launcher.png b/bindings/kotlin/sample/src/main/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 64ba76f75..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/bindings/kotlin/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png
deleted file mode 100644
index dae5e0823..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/bindings/kotlin/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index e5ed46597..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/bindings/kotlin/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
deleted file mode 100644
index 14ed0af35..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/bindings/kotlin/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index b0907cac3..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/bindings/kotlin/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
deleted file mode 100644
index d8ae03154..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/bindings/kotlin/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 2c18de9e6..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/bindings/kotlin/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
deleted file mode 100644
index beed3cdd2..000000000
Binary files a/bindings/kotlin/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/bindings/kotlin/sample/src/main/res/values/colors.xml b/bindings/kotlin/sample/src/main/res/values/colors.xml
deleted file mode 100644
index 69b22338c..000000000
--- a/bindings/kotlin/sample/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <color name="colorPrimary">#008577</color>
- <color name="colorPrimaryDark">#00574B</color>
- <color name="colorAccent">#D81B60</color>
-</resources>
diff --git a/bindings/kotlin/sample/src/main/res/values/strings.xml b/bindings/kotlin/sample/src/main/res/values/strings.xml
deleted file mode 100644
index 50ca77cff..000000000
--- a/bindings/kotlin/sample/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<resources>
- <string name="app_name">stretch</string>
-</resources>
diff --git a/bindings/kotlin/sample/src/main/res/values/styles.xml b/bindings/kotlin/sample/src/main/res/values/styles.xml
deleted file mode 100644
index 5885930df..000000000
--- a/bindings/kotlin/sample/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<resources>
-
- <!-- Base application theme. -->
- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
- <!-- Customize your theme here. -->
- <item name="colorPrimary">@color/colorPrimary</item>
- <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
- <item name="colorAccent">@color/colorAccent</item>
- </style>
-
-</resources>
diff --git a/bindings/kotlin/settings.gradle b/bindings/kotlin/settings.gradle
index 32450087d..7f07d77b1 100644
--- a/bindings/kotlin/settings.gradle
+++ b/bindings/kotlin/settings.gradle
@@ -1 +1 @@
-include ':sample', ':stretch'
+include ':stretch'
diff --git a/bindings/kotlin/stretch/build.gradle b/bindings/kotlin/stretch/build.gradle
index 5673f010c..1409021ce 100644
--- a/bindings/kotlin/stretch/build.gradle
+++ b/bindings/kotlin/stretch/build.gradle
@@ -11,7 +11,7 @@ android {
versionCode 1
versionName "1.0"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -30,6 +30,20 @@ android {
}
}
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "androidx.core:core:1.0.1"
+
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.1.1'
+ androidTestImplementation 'androidx.test:rules:1.1.1'
+ androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
+}
+
def rustBasePath = "src/main/rust"
def cargoOutputDir = "${rustBasePath}/target"
def archTriplets = ['arm64-v8a': 'aarch64-linux-android',
@@ -65,9 +79,3 @@ archTriplets.each { arch, target ->
clean.dependsOn "clean-${arch}"
}
-repositories {
- mavenCentral()
-}
-dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-}
diff --git a/bindings/kotlin/stretch/src/androidTest/java/app/visly/stretch/NodeTest.kt b/bindings/kotlin/stretch/src/androidTest/java/app/visly/stretch/NodeTest.kt
new file mode 100644
index 000000000..fd90b6d6e
--- /dev/null
+++ b/bindings/kotlin/stretch/src/androidTest/java/app/visly/stretch/NodeTest.kt
@@ -0,0 +1,101 @@
+package app.visly.stretch
+
+import org.hamcrest.CoreMatchers.*
+import org.hamcrest.MatcherAssert.*
+import org.junit.Test
+
+class NodeTest {
+
+ @Test
+ fun createNode() {
+ val child = Node(Style(), listOf())
+ val node = Node(Style(), listOf(child))
+ assertThat(node.getChildCount(), `is`(1))
+ }
+
+ @Test
+ fun createLeaf() {
+ val node = Node(Style(), object: MeasureFunc {
+ override fun measure(constraints: Size<Float?>): Size<Float> {
+ return Size(100f, 100f)
+ }
+ })
+
+ val layout = node.computeLayout(Size(null, null))
+ assertThat(layout.width, `is`(100f))
+ assertThat(layout.height, `is`(100f))
+ }
+
+ @Test
+ fun setMeasure() {
+ val node = Node(Style(), listOf())
+ node.setMeasure(object: MeasureFunc {
+ override fun measure(constraints: Size<Float?>): Size<Float> {
+ return Size(100f, 100f)
+ }
+ })
+
+ val layout = node.computeLayout(Size(null, null))
+ assertThat(layout.width, `is`(100f))
+ assertThat(layout.height, `is`(100f))
+ }
+
+ @Test
+ fun addChild() {
+ val node = Node(Style(), listOf())
+ val child = Node(Style(), listOf())
+ node.addChild(child)
+ assertThat(node.getChildCount(), `is`(1))
+ }
+
+ @Test
+ fun removeChild() {
+ val child = Node(Style(), listOf())
+ val node = Node(Style(), listOf(child))
+ node.removeChild(child)
+ assertThat(node.getChildCount(), `is`(0))
+ }
+
+ @Test
+ fun removeChildAtIndex() {
+ val child = Node(Style(), listOf())
+ val node = Node(Style(), listOf(child))
+ node.removeChildAtIndex(0)
+ assertThat(node.getChildCount(), `is`(0))
+ }
+
+ @Test
+ fun replaceChildAtIndex() {
+ val child1 = Node(Style(size = Size(Dimension.Points(100f), Dimension.Points(100f))), listOf())
+ val child2 = Node(Style(size = Size(Dimension.Points(200f), Dimension.Points(200f))), listOf())
+ val node = Node(Style(), listOf(child1))
+ node.replaceChildAtIndex(0, child2)
+
+ val layout = node.computeLayout(Size(null, null))
+ assertThat(layout.width, `is`(200f))
+ assertThat(layout.height, `is`(200f))
+ }
+
+ @Test
+ fun setStyle() {
+ val node = Node(Style(), listOf())
+ node.setStyle(Style())
+ }
+
+ @Test
+ fun setChildren() {
+ val node = Node(Style(), listOf())
+ val child = Node(Style(), listOf())
+ node.setChildren(listOf(child))
+ assertThat(node.getChildCount(), `is`(1))
+ }
+
+ @Test
+ fun markDirty() {
+ val node = Node(Style(), listOf())
+ node.computeLayout(Size(null, null))
+ assertThat(node.isDirty(), `is`(false))
+ node.markDirty()
+ assertThat(node.isDirty(), `is`(true))
+ }
+}
\ No newline at end of file
diff --git a/bindings/kotlin/stretch/src/androidTest/java/app/visly/stretch/StretchTestSuite.kt b/bindings/kotlin/stretch/src/androidTest/java/app/visly/stretch/StretchTestSuite.kt
new file mode 100644
index 000000000..055475676
--- /dev/null
+++ b/bindings/kotlin/stretch/src/androidTest/java/app/visly/stretch/StretchTestSuite.kt
@@ -0,0 +1,8 @@
+package app.visly.stretch
+
+import org.junit.runner.RunWith
+import org.junit.runners.Suite
+
+@RunWith(Suite::class)
+@Suite.SuiteClasses(NodeTest::class)
+class StretchTestSuite
\ No newline at end of file
diff --git a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Layout.kt b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Layout.kt
index fb6458f85..bb699452b 100644
--- a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Layout.kt
+++ b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Layout.kt
@@ -8,7 +8,7 @@ data class Layout(
val children: List<Layout>) {
companion object {
- fun fromFloatArray(args: FloatArray, offset: Int): Pair<Int, Layout> {
+ internal fun fromFloatArray(args: FloatArray, offset: Int): Pair<Int, Layout> {
var offset = offset
val x = args[offset++]
diff --git a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Node.kt b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Node.kt
index 5dec50ac8..32494f754 100644
--- a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Node.kt
+++ b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Node.kt
@@ -1,8 +1,13 @@
package app.visly.stretch
+import androidx.annotation.Keep
-private class MeasureFunc(val measure: (Size<Float?>) -> Size<Float>) {
- fun measure(width: Float, height: Float): FloatArray {
- val result = measure(Size(
+interface MeasureFunc {
+ fun measure(constraints: Size<Float?>): Size<Float>
+}
+
+private class MeasureFuncImpl(val measureFunc: MeasureFunc) {
+ @Keep fun measure(width: Float, height: Float): FloatArray {
+ val result = measureFunc.measure(Size(
if (width.isNaN()) null else width,
if (height.isNaN()) null else height
))
@@ -13,16 +18,16 @@ private class MeasureFunc(val measure: (Size<Float?>) -> Size<Float>) {
class Node {
companion object {
init {
- System.loadLibrary("stretch")
+ Stretch.init()
}
}
- internal val rustptr: Long
+ private val rustptr: Long
private var style: Style
private var children: MutableList<Node>
- constructor(style: Style, measure: (Size<Float?>) -> Size<Float>) {
- this.rustptr = nConstructLeaf(style.rustptr, MeasureFunc(measure))
+ constructor(style: Style, measure: MeasureFunc) {
+ this.rustptr = nConstructLeaf(style.rustptr, MeasureFuncImpl(measure))
this.style = style
this.children = mutableListOf()
}
@@ -37,6 +42,10 @@ class Node {
nFree(rustptr)
}
+ fun setMeasure(measure: MeasureFunc) {
+ nSetMeasure(rustptr, MeasureFuncImpl(measure))
+ }
+
fun getChildren(): List<Node> {
return this.children
}
@@ -84,8 +93,8 @@ class Node {
return nIsDirty(rustptr)
}
- fun childCount(): Int {
- return nChildCount(rustptr)
+ fun getChildCount(): Int {
+ return children.size
}
fun computeLayout(size: Size<Float?>): Layout {
@@ -93,10 +102,10 @@ class Node {
return result.second
}
- private external fun nFree(ptr: Long)
- private external fun nChildCount(ptr: Long): Int
private external fun nConstruct(style: Long, children: LongArray): Long
- private external fun nConstructLeaf(style: Long, measure: MeasureFunc): Long
+ private external fun nConstructLeaf(style: Long, measure: MeasureFuncImpl): Long
+ private external fun nFree(ptr: Long)
+ private external fun nSetMeasure(ptr: Long, measure: MeasureFuncImpl)
private external fun nSetChildren(ptr: Long, children: LongArray)
private external fun nAddChild(ptr: Long, child: Long)
private external fun nReplaceChildAtIndex(ptr: Long, index: Int, child: Long): Long
diff --git a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Stretch.kt b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Stretch.kt
new file mode 100644
index 000000000..149c6c82f
--- /dev/null
+++ b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Stretch.kt
@@ -0,0 +1,18 @@
+package app.visly.stretch
+
+// TODO
+// - Change measure to be a weak ref to node instance which in turn calls passed in measure function implementation from java.
+// Problem with this is jni library currently does not support weak refs. This can be worked around by creating weak ref on java side.
+// - Integration tests to ensure bindings don't break
+
+class Stretch {
+ companion object {
+ private var didInit = false
+ internal fun init() {
+ if (!didInit) {
+ System.loadLibrary("stretch")
+ didInit = true
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Style.kt b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Style.kt
index 28b888997..54244fbbd 100644
--- a/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Style.kt
+++ b/bindings/kotlin/stretch/src/main/java/app/visly/stretch/Style.kt
@@ -93,10 +93,6 @@ sealed class Dimension {
}
}
-data class FloatSize(
- val width: Float,
- val height: Float)
-
data class Size<T>(
val width: T,
val height: T)
@@ -132,7 +128,7 @@ data class Style(
companion object {
init {
- System.loadLibrary("stretch")
+ Stretch.init()
}
}
@@ -289,4 +285,160 @@ data class Style(
aspectRatio: Float
): Long
+
+ // This class exists for use with Java which does not have support for named / default arguments as in kotlin.
+ class Builder {
+ private var display: Display = Display.Flex
+ private var positionType: PositionType = PositionType.Relative
+ private var direction: Direction = Direction.Inherit
+ private var flexDirection: FlexDirection = FlexDirection.Row
+ private var flexWrap: FlexWrap = FlexWrap.NoWrap
+ private var overflow: Overflow = Overflow.Hidden
+ private var alignItems: AlignItems = AlignItems.Stretch
+ private var alignSelf: AlignSelf = AlignSelf.Auto
+ private var alignContent: AlignContent = AlignContent.FlexStart
+ private var justifyContent: JustifyContent = JustifyContent.FlexStart
+ private var position: Rect<Dimension> = Rect(Dimension.Undefined, Dimension.Undefined, Dimension.Undefined, Dimension.Undefined)
+ private var margin: Rect<Dimension> = Rect(Dimension.Undefined, Dimension.Undefined, Dimension.Undefined, Dimension.Undefined)
+ private var padding: Rect<Dimension> = Rect(Dimension.Undefined, Dimension.Undefined, Dimension.Undefined, Dimension.Undefined)
+ private var border: Rect<Dimension> = Rect(Dimension.Undefined, Dimension.Undefined, Dimension.Undefined, Dimension.Undefined)
+ private var flexGrow: Float = 0f
+ private var flexShrink: Float = 1f
+ private var flexBasis: Dimension = Dimension.Auto
+ private var size: Size<Dimension> = Size(Dimension.Auto, Dimension.Auto)
+ private var minSize: Size<Dimension> = Size(Dimension.Auto, Dimension.Auto)
+ private var maxSize: Size<Dimension> = Size(Dimension.Auto, Dimension.Auto)
+ private var aspectRatio: Float? = null
+
+ fun build(): Style {
+ return Style(
+ display,
+ positionType,
+ direction,
+ flexDirection,
+ flexWrap,
+ overflow,
+ alignItems,
+ alignSelf,
+ alignContent,
+ justifyContent,
+ position,
+ margin,
+ padding,
+ border,
+ flexGrow,
+ flexShrink,
+ flexBasis,
+ size,
+ minSize,
+ maxSize,
+ aspectRatio
+ )
+ }
+
+ fun display(display: Display): Builder {
+ this.display = display
+ return this
+ }
+
+ fun positionType(positionType: PositionType): Builder {
+ this.positionType = positionType
+ return this
+ }
+
+ fun direction(direction: Direction): Builder {
+ this.direction = direction
+ return this
+ }
+
+ fun flexDirection(flexDirection: FlexDirection): Builder {
+ this.flexDirection = flexDirection
+ return this
+ }
+
+ fun flexWrap(flexWrap: FlexWrap): Builder {
+ this.flexWrap = flexWrap
+ return this
+ }
+
+ fun overflow(overflow: Overflow): Builder {
+ this.overflow = overflow
+ return this
+ }
+
+ fun alignItems(alignItems: AlignItems): Builder {
+ this.alignItems = alignItems
+ return this
+ }
+
+ fun alignSelf(alignSelf: AlignSelf): Builder {
+ this.alignSelf = alignSelf
+ return this
+ }
+
+ fun alignContent(alignContent: AlignContent): Builder {
+ this.alignContent = alignContent
+ return this
+ }
+
+ fun justifyContent(justifyContent: JustifyContent): Builder {
+ this.justifyContent = justifyContent
+ return this
+ }
+
+ fun position(position: Rect<Dimension>): Builder {
+ this.position = position
+ return this
+ }
+
+ fun margin(margin: Rect<Dimension>): Builder {
+ this.margin = margin
+ return this
+ }
+
+ fun padding(padding: Rect<Dimension>): Builder {
+ this.padding = padding
+ return this
+ }
+
+ fun border(border: Rect<Dimension>): Builder {
+ this.border = border
+ return this
+ }
+
+ fun flexGrow(flexGrow: Float): Builder {
+ this.flexGrow = flexGrow
+ return this
+ }
+
+ fun flexShrink(flexShrink: Float): Builder {
+ this.flexShrink = flexShrink
+ return this
+ }
+
+ fun flexBasis(flexBasis: Dimension): Builder {
+ this.flexBasis = flexBasis
+ return this
+ }
+
+ fun size(size: Size<Dimension>): Builder {
+ this.size = size
+ return this
+ }
+
+ fun minSize(minSize: Size<Dimension>): Builder {
+ this.minSize = minSize
+ return this
+ }
+
+ fun maxSize(maxSize: Size<Dimension>): Builder {
+ this.maxSize = maxSize
+ return this
+ }
+
+ fun aspectRatio(aspectRatio: Float?): Builder {
+ this.aspectRatio = aspectRatio
+ return this
+ }
+ }
}
diff --git a/bindings/kotlin/stretch/src/main/libs/arm64-v8a/libstretch.so b/bindings/kotlin/stretch/src/main/libs/arm64-v8a/libstretch.so
index 4d05d07d5..62b879c13 100755
Binary files a/bindings/kotlin/stretch/src/main/libs/arm64-v8a/libstretch.so and b/bindings/kotlin/stretch/src/main/libs/arm64-v8a/libstretch.so differ
diff --git a/bindings/kotlin/stretch/src/main/libs/armeabi-v7a/libstretch.so b/bindings/kotlin/stretch/src/main/libs/armeabi-v7a/libstretch.so
index bcca778e9..6b9df4547 100755
Binary files a/bindings/kotlin/stretch/src/main/libs/armeabi-v7a/libstretch.so and b/bindings/kotlin/stretch/src/main/libs/armeabi-v7a/libstretch.so differ
diff --git a/bindings/kotlin/stretch/src/main/libs/x86/libstretch.so b/bindings/kotlin/stretch/src/main/libs/x86/libstretch.so
index f39f1cdba..4a2fca50f 100755
Binary files a/bindings/kotlin/stretch/src/main/libs/x86/libstretch.so and b/bindings/kotlin/stretch/src/main/libs/x86/libstretch.so differ
diff --git a/bindings/kotlin/stretch/src/main/rust/Cargo.toml b/bindings/kotlin/stretch/src/main/rust/Cargo.toml
index 9a73d2b9b..760b33c13 100644
--- a/bindings/kotlin/stretch/src/main/rust/Cargo.toml
+++ b/bindings/kotlin/stretch/src/main/rust/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
[dependencies]
jni = { version = "0.10.2", default-features = false }
-stretch = "0.2.1"
+stretch = "0.2.2"
[lib]
name = "stretch"
diff --git a/bindings/kotlin/stretch/src/main/rust/src/lib.rs b/bindings/kotlin/stretch/src/main/rust/src/lib.rs
index b5c3881dd..04a32c925 100644
--- a/bindings/kotlin/stretch/src/main/rust/src/lib.rs
+++ b/bindings/kotlin/stretch/src/main/rust/src/lib.rs
@@ -274,7 +274,7 @@ pub unsafe extern "C" fn Java_app_visly_stretch_Node_nConstructLeaf(
) -> jlong {
let measure = env.new_global_ref(measure).unwrap();
let style: Box<Style> = Box::from_raw(style as *mut Style);
- let node = Node::new_leaf(*Box::leak(style), Some(Box::new(move |constraint| {
+ let node = Node::new_leaf(*Box::leak(style), Box::new(move |constraint| {
let result = env.call_method(
measure.as_obj(),
"measure",
@@ -291,7 +291,7 @@ pub unsafe extern "C" fn Java_app_visly_stretch_Node_nConstructLeaf(
}
Err(err) => Err(Box::new(err)),
}
- })));
+ }));
Box::into_raw(Box::new(node)) as jlong
}
@@ -305,13 +305,33 @@ pub unsafe extern "C" fn Java_app_visly_stretch_Node_nFree(
}
#[no_mangle]
-pub unsafe extern "C" fn Java_app_visly_stretch_Node_nChildCount(
- _: JNIEnv,
+pub unsafe extern "C" fn Java_app_visly_stretch_Node_nSetMeasure(
+ env: JNIEnv<'static>,
_: JObject,
node: jlong,
-) -> jint {
+ measure: JObject,
+) {
+ let measure = env.new_global_ref(measure).unwrap();
let node: Box<Node> = Box::from_raw(node as *mut Node);
- Box::leak(node).children().len() as i32
+
+ Box::leak(node).set_measure(Some(Box::new(move |constraint| {
+ let result = env.call_method(
+ measure.as_obj(),
+ "measure",
+ "(FF)[F",
+ &[JValue::from(constraint.width.or_else(f32::NAN)), JValue::from(constraint.height.or_else(f32::NAN))],
+ );
+
+ match result {
+ Ok(result) => {
+ let size = result.l().unwrap().into_inner() as jfloatArray;
+ let mut buff: [f32; 2] = [0.0, 0.0];
+ env.get_float_array_region(size, 0, &mut buff).unwrap();
+ Ok(Size { width: buff[0], height: buff[1] })
+ }
+ Err(err) => Err(Box::new(err)),
+ }
+ })));
}
#[no_mangle]
diff --git a/src/node.rs b/src/node.rs
index e9369b1a7..5221c464a 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -26,12 +26,12 @@ pub(crate) struct InternalNode {
pub struct Node(Rc<RefCell<InternalNode>>);
impl Node {
- pub fn new_leaf(style: Style, measure: Option<MeasureFunc>) -> Node {
+ pub fn new_leaf(style: Style, measure: MeasureFunc) -> Node {
Node(Rc::new(RefCell::new(InternalNode {
style,
parents: Vec::with_capacity(1),
children: Vec::with_capacity(0),
- measure,
+ measure: Some(measure),
layout_cache: None,
is_dirty: true,
})))
@@ -55,6 +55,11 @@ impl Node {
parent
}
+ pub fn set_measure(&mut self, measure: Option<MeasureFunc>) {
+ self.0.borrow_mut().measure = measure;
+ self.mark_dirty();
+ }
+
pub fn add_child(&mut self, child: &Node) {
child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
self.0.borrow_mut().children.push(Rc::clone(&child.0));
@@ -117,6 +122,11 @@ impl Node {
node.children.iter().map(|child| Node(Rc::clone(child))).collect()
}
+ pub fn child_count(&self) -> usize {
+ let node = self.0.borrow_mut();
+ node.children.len()
+ }
+
pub fn set_style(&mut self, style: Style) {
self.0.borrow_mut().style = style;
self.mark_dirty();
diff --git a/tests/measure.rs b/tests/measure.rs
index afed43f61..a5f3fb7f0 100644
--- a/tests/measure.rs
+++ b/tests/measure.rs
@@ -6,12 +6,12 @@ mod measure {
fn measure_root() {
let layout = stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)
.compute_layout(stretch::geometry::Size::undefined())
.unwrap();
@@ -26,12 +26,12 @@ mod measure {
stretch::style::Style { ..Default::default() },
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -53,12 +53,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -86,12 +86,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -124,12 +124,12 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(10.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
),
],
)
@@ -161,12 +161,12 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
),
],
)
@@ -198,11 +198,11 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
let width = constraint.width.or_else(10.0);
let height = constraint.height.or_else(width * 2.0);
Ok(stretch::geometry::Size { width, height })
- })),
+ }),
),
],
)
@@ -235,11 +235,11 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
let width = constraint.width.or_else(100.0);
let height = constraint.height.or_else(width * 2.0);
Ok(stretch::geometry::Size { width, height })
- })),
+ }),
),
],
)
@@ -262,11 +262,11 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
let height = constraint.height.or_else(50.0);
let width = constraint.width.or_else(height);
Ok(stretch::geometry::Size { width, height })
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -288,12 +288,12 @@ mod measure {
},
..Default::default()
},
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -315,12 +315,12 @@ mod measure {
},
..Default::default()
},
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -355,12 +355,12 @@ mod measure {
flex_grow: 1.0,
..Default::default()
},
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
),
],
)
@@ -385,12 +385,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(50.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -412,12 +412,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { position_type: stretch::style::PositionType::Absolute, ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(50.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -439,7 +439,7 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|_| Ok(stretch::geometry::Size { width: 200.0, height: 200.0 }))),
+ Box::new(|_| Ok(stretch::geometry::Size { width: 200.0, height: 200.0 })),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -460,13 +460,13 @@ mod measure {
stretch::style::Style { ..Default::default() },
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(move |constraint| {
+ Box::new(move |constraint| {
unsafe { (*num_measure_ptr) += 1 };
Ok(stretch::geometry::Size {
width: constraint.width.or_else(50.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
)],
)],
)
@@ -488,7 +488,7 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|_| Err(Box::new("")))),
+ Box::new(|_| Err(Box::new(""))),
)],
)
.compute_layout(stretch::geometry::Size::undefined());
diff --git a/tests/node.rs b/tests/node.rs
index 1f29dddaf..ea35cb990 100644
--- a/tests/node.rs
+++ b/tests/node.rs
@@ -1,5 +1,6 @@
#[cfg(test)]
mod node {
+ use stretch::geometry::*;
use stretch::node::Node;
use stretch::style::*;
@@ -9,21 +10,30 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
assert_eq!(node.children()[0], child1);
assert_eq!(node.children()[1], child2);
}
+ #[test]
+ fn set_measure() {
+ let mut node = Node::new_leaf(Style::default(), Box::new(|_| Ok(Size { width: 200.0, height: 200.0 })));
+ assert_eq!(node.compute_layout(Size::undefined()).unwrap().size.width, 200.0);
+
+ node.set_measure(Some(Box::new(|_| Ok(Size { width: 100.0, height: 100.0 }))));
+ assert_eq!(node.compute_layout(Size::undefined()).unwrap().size.width, 100.0);
+ }
+
#[test]
fn add_child() {
let mut node = Node::new(Style::default(), vec![]);
- assert_eq!(node.children().len(), 0);
+ assert_eq!(node.child_count(), 0);
node.add_child(&Node::new(Style::default(), vec![]));
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
node.add_child(&Node::new(Style::default(), vec![]));
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
}
#[test]
@@ -32,14 +42,14 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
node.remove_child(&child1);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child2);
node.remove_child(&child2);
- assert_eq!(node.children().len(), 0);
+ assert_eq!(node.child_count(), 0);
}
#[test]
@@ -48,14 +58,14 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
node.remove_child_at_index(0);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child2);
node.remove_child_at_index(0);
- assert_eq!(node.children().len(), 0);
+ assert_eq!(node.child_count(), 0);
}
#[test]
@@ -64,11 +74,11 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1]);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child1);
node.replace_child_at_index(0, &child2);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child2);
}
@@ -78,7 +88,7 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
assert_eq!(node.children()[0], child1);
assert_eq!(node.children()[1], child2);
@@ -86,7 +96,7 @@ mod node {
let child4 = Node::new(Style::default(), vec![]);
node.set_children(vec![&child3, &child4]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
assert_eq!(node.children()[0], child3);
assert_eq!(node.children()[1], child4);
}