From 60bbbbc6eb61f983e4b24029a74ca227b98adfa8 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Thu, 9 Jan 2025 19:49:27 +0100 Subject: [PATCH] wip examples --- .gitignore | 3 + .../build.gradle.kts | 4 + .../nl/jolanrensen/example/Alignment.kt | 288 ++++++++++++++++++ .../kotlin/nl/jolanrensen/example/MathH1.kt | 34 +++ .../kotlin/nl/jolanrensen/example/MathH2.kt | 55 ++++ .../kotlin/nl/jolanrensen/example/MathH3.kt | 54 ++++ .../example/{MathH.kt => MathH4.kt} | 25 +- .../.gradle/8.5/checksums/checksums.lock | Bin 17 -> 17 bytes .../.gradle/8.5/checksums/sha1-checksums.bin | Bin 19307 -> 19307 bytes .../dependencies-accessors.lock | Bin 17 -> 17 bytes .../.gradle/8.5/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../buildOutputCleanup/outputFiles.bin | Bin 22511 -> 22601 bytes 13 files changed, 453 insertions(+), 10 deletions(-) create mode 100644 kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/Alignment.kt create mode 100644 kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH1.kt create mode 100644 kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH2.kt create mode 100644 kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH3.kt rename kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/{MathH.kt => MathH4.kt} (62%) diff --git a/.gitignore b/.gitignore index 35369634..695072af 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ hs_err_pid* /.idea/ /kodex-gradle-plugin/src/functionalTest/resources/dataframe/ .intellijPlatform +/kodex-example-gradle-project-multiplatform/.gradle/ +/kodex-example-gradle-project-multiplatform/.kotlin/ +/kodex-example-gradle-project-multiplatform/build/ diff --git a/kodex-example-gradle-project-jvm/build.gradle.kts b/kodex-example-gradle-project-jvm/build.gradle.kts index 31c604b2..d76cf5c7 100644 --- a/kodex-example-gradle-project-jvm/build.gradle.kts +++ b/kodex-example-gradle-project-jvm/build.gradle.kts @@ -12,6 +12,7 @@ version = "1.0" repositories { mavenCentral() + google() } kotlin { @@ -21,6 +22,9 @@ kotlin { dependencies { implementation("org.jetbrains.kotlinx:dataframe:0.15.0") testImplementation(kotlin("test")) + + implementation("androidx.compose.runtime:runtime:1.7.6") + implementation("androidx.compose.ui:ui:1.7.6") } kodex { diff --git a/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/Alignment.kt b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/Alignment.kt new file mode 100644 index 00000000..8bd3bd9a --- /dev/null +++ b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/Alignment.kt @@ -0,0 +1,288 @@ +package nl.jolanrensen.example + +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.util.fastRoundToInt + +/** + * An interface to calculate the position of a sized box inside an available space. [Alignment] is + * often used to define the alignment of a layout inside a parent layout. + * + * @see AbsoluteAlignment + * @see BiasAlignment + * @see BiasAbsoluteAlignment + */ +@Stable +fun interface Alignment { + /** + * Calculates the position of a box of size [size] relative to the top left corner of an area of + * size [space]. The returned offset can be negative or larger than `space - size`, meaning that + * the box will be positioned partially or completely outside the area. + */ + fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset + + /** + * An interface to calculate the position of box of a certain {@get DIMENSION} inside an available {@get DIMENSION}. + * [Alignment.Horizontal] is often used to define the horizontal alignment of a layout inside a + * parent layout. + */ + @ExcludeFromSources private interface AlignmentDocs { + interface DIMENSION + interface REF + } + + /** + * An interface to calculate the position of box of a certain width inside an available width. + * [Alignment.Horizontal] is often used to define the horizontal alignment of a layout inside a + * parent layout. + */ + @Stable + fun interface Horizontal { + /** + * Calculates the horizontal position of a box of width [size] relative to the left side of + * an area of width [space]. The returned offset can be negative or larger than `space - + * size` meaning that the box will be positioned partially or completely outside the area. + */ + fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int + + /** + * Combine this instance's horizontal alignment with [other]'s vertical alignment to create + * an [Alignment]. + */ + operator fun plus(other: Vertical): Alignment = CombinedAlignment(this, other) + } + + /** + * An interface to calculate the position of a box of a certain height inside an available + * height. [Alignment.Vertical] is often used to define the vertical alignment of a layout + * inside a parent layout. + */ + @Stable + fun interface Vertical { + /** + * Calculates the vertical position of a box of height [size] relative to the top edge of an + * area of height [space]. The returned offset can be negative or larger than `space - size` + * meaning that the box will be positioned partially or completely outside the area. + */ + fun align(size: Int, space: Int): Int + + /** + * Combine this instance's vertical alignment with [other]'s horizontal alignment to create + * an [Alignment]. + */ + operator fun plus(other: Horizontal): Alignment = CombinedAlignment(other, this) + } + + /** A collection of common [Alignment]s aware of layout direction. */ + companion object { + // 2D Alignments. + @Stable val TopStart: Alignment = BiasAlignment(-1f, -1f) + @Stable val TopCenter: Alignment = BiasAlignment(0f, -1f) + @Stable val TopEnd: Alignment = BiasAlignment(1f, -1f) + @Stable val CenterStart: Alignment = BiasAlignment(-1f, 0f) + @Stable val Center: Alignment = BiasAlignment(0f, 0f) + @Stable val CenterEnd: Alignment = BiasAlignment(1f, 0f) + @Stable val BottomStart: Alignment = BiasAlignment(-1f, 1f) + @Stable val BottomCenter: Alignment = BiasAlignment(0f, 1f) + @Stable val BottomEnd: Alignment = BiasAlignment(1f, 1f) + + // 1D Alignment.Verticals. + @Stable val Top: Vertical = BiasAlignment.Vertical(-1f) + @Stable val CenterVertically: Vertical = BiasAlignment.Vertical(0f) + @Stable val Bottom: Vertical = BiasAlignment.Vertical(1f) + + // 1D Alignment.Horizontals. + @Stable val Start: Horizontal = BiasAlignment.Horizontal(-1f) + @Stable val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f) + @Stable val End: Horizontal = BiasAlignment.Horizontal(1f) + } +} + +private class CombinedAlignment( + private val horizontal: Alignment.Horizontal, + private val vertical: Alignment.Vertical, +) : Alignment { + override fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset { + val x = horizontal.align(size.width, space.width, layoutDirection) + val y = vertical.align(size.height, space.height) + return IntOffset(x, y) + } +} + +/** A collection of common [Alignment]s unaware of the layout direction. */ +object AbsoluteAlignment { + // 2D AbsoluteAlignments. + @Stable val TopLeft: Alignment = BiasAbsoluteAlignment(-1f, -1f) + @Stable val TopRight: Alignment = BiasAbsoluteAlignment(1f, -1f) + @Stable val CenterLeft: Alignment = BiasAbsoluteAlignment(-1f, 0f) + @Stable val CenterRight: Alignment = BiasAbsoluteAlignment(1f, 0f) + @Stable val BottomLeft: Alignment = BiasAbsoluteAlignment(-1f, 1f) + @Stable val BottomRight: Alignment = BiasAbsoluteAlignment(1f, 1f) + + // 1D BiasAbsoluteAlignment.Horizontals. + @Stable val Left: Alignment.Horizontal = BiasAbsoluteAlignment.Horizontal(-1f) + @Stable val Right: Alignment.Horizontal = BiasAbsoluteAlignment.Horizontal(1f) +} + +/** + * An [Alignment] specified by bias: for example, a bias of -1 represents alignment to the + * start/top, a bias of 0 will represent centering, and a bias of 1 will represent end/bottom. Any + * value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained alignment + * will position the aligned size fully inside the available space, while outside the range it will + * the aligned size will be positioned partially or completely outside. + * + * @see BiasAbsoluteAlignment + * @see Alignment + */ +@Immutable +data class BiasAlignment(val horizontalBias: Float, val verticalBias: Float) : Alignment { + override fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset { + // Convert to Px first and only round at the end, to avoid rounding twice while calculating + // the new positions + val centerX = (space.width - size.width).toFloat() / 2f + val centerY = (space.height - size.height).toFloat() / 2f + val resolvedHorizontalBias = + if (layoutDirection == LayoutDirection.Ltr) { + horizontalBias + } else { + -1 * horizontalBias + } + + val x = centerX * (1 + resolvedHorizontalBias) + val y = centerY * (1 + verticalBias) + return IntOffset(x.fastRoundToInt(), y.fastRoundToInt()) + } + + /** + * An [Alignment.Horizontal] specified by bias: for example, a bias of -1 represents alignment + * to the start, a bias of 0 will represent centering, and a bias of 1 will represent end. Any + * value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained + * alignment will position the aligned size fully inside the available space, while outside the + * range it will the aligned size will be positioned partially or completely outside. + * + * @see BiasAbsoluteAlignment.Horizontal + * @see Vertical + */ + @Immutable + data class Horizontal(val bias: Float) : Alignment.Horizontal { + override fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int { + // Convert to Px first and only round at the end, to avoid rounding twice while + // calculating the new positions + val center = (space - size).toFloat() / 2f + val resolvedBias = if (layoutDirection == LayoutDirection.Ltr) bias else -1 * bias + return (center * (1 + resolvedBias)).fastRoundToInt() + } + + override fun plus(other: Alignment.Vertical): Alignment { + return when (other) { + is Vertical -> BiasAlignment(bias, other.bias) + else -> super.plus(other) + } + } + } + + /** + * An [Alignment.Vertical] specified by bias: for example, a bias of -1 represents alignment to + * the top, a bias of 0 will represent centering, and a bias of 1 will represent bottom. Any + * value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained + * alignment will position the aligned size fully inside the available space, while outside the + * range it will the aligned size will be positioned partially or completely outside. + * + * @see Horizontal + */ + @Immutable + data class Vertical(val bias: Float) : Alignment.Vertical { + override fun align(size: Int, space: Int): Int { + // Convert to Px first and only round at the end, to avoid rounding twice while + // calculating the new positions + val center = (space - size).toFloat() / 2f + return (center * (1 + bias)).fastRoundToInt() + } + + override fun plus(other: Alignment.Horizontal): Alignment { + return when (other) { + is Horizontal -> BiasAlignment(other.bias, bias) + is BiasAbsoluteAlignment.Horizontal -> BiasAbsoluteAlignment(other.bias, bias) + else -> super.plus(other) + } + } + } +} + +/** + * An [Alignment] specified by bias: for example, a bias of -1 represents alignment to the left/top, + * a bias of 0 will represent centering, and a bias of 1 will represent right/bottom. Any value can + * be specified to obtain an alignment. Inside the [-1, 1] range, the obtained alignment will + * position the aligned size fully inside the available space, while outside the range it will the + * aligned size will be positioned partially or completely outside. + * + * @see AbsoluteAlignment + * @see Alignment + */ +@Immutable +data class BiasAbsoluteAlignment(val horizontalBias: Float, val verticalBias: Float) : Alignment { + /** + * Returns the position of a 2D point in a container of a given size, according to this + * [BiasAbsoluteAlignment]. The position will not be mirrored in Rtl context. + */ + override fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset { + // Convert to Px first and only round at the end, to avoid rounding twice while calculating + // the new positions + val remaining = IntSize(space.width - size.width, space.height - size.height) + val centerX = remaining.width.toFloat() / 2f + val centerY = remaining.height.toFloat() / 2f + + val x = centerX * (1 + horizontalBias) + val y = centerY * (1 + verticalBias) + return IntOffset(x.fastRoundToInt(), y.fastRoundToInt()) + } + + /** + * An [Alignment.Horizontal] specified by bias: for example, a bias of -1 represents alignment + * to the left, a bias of 0 will represent centering, and a bias of 1 will represent right. Any + * value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained + * alignment will position the aligned size fully inside the available space, while outside the + * range it will the aligned size will be positioned partially or completely outside. + * + * @see BiasAlignment.Horizontal + */ + @Immutable + data class Horizontal(val bias: Float) : Alignment.Horizontal { + /** + * Returns the position of a 2D point in a container of a given size, according to this + * [BiasAbsoluteAlignment.Horizontal]. This position will not be mirrored in Rtl context. + */ + override fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int { + // Convert to Px first and only round at the end, to avoid rounding twice while + // calculating the new positions + val center = (space - size).toFloat() / 2f + return (center * (1 + bias)).fastRoundToInt() + } + + override fun plus(other: Alignment.Vertical): Alignment { + return when (other) { + is BiasAlignment.Vertical -> BiasAbsoluteAlignment(bias, other.bias) + else -> super.plus(other) + } + } + } +} diff --git a/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH1.kt b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH1.kt new file mode 100644 index 00000000..1babd1d0 --- /dev/null +++ b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH1.kt @@ -0,0 +1,34 @@ +package nl.jolanrensen.example + +interface MathH1 { + + /** + * Computes the cosine of the angle [x] given in degrees. + * + * Special cases: + * - `cos(NaN|+Inf|-Inf)` is `NaN` + * + * @param x the angle in degrees + * @return the cosine of the angle [x] + */ + fun cos(x: Double): Double + + /** + * ... + */ + fun cos(x: Float): Double + + fun cos(x: Int): Double + + fun sin(x: Double): Double + + fun sin(x: Float): Double + + fun sin(x: Int): Double + + fun tan(x: Double): Double + + fun tan(x: Float): Double + + fun tan(x: Int): Double +} diff --git a/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH2.kt b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH2.kt new file mode 100644 index 00000000..f1f06130 --- /dev/null +++ b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH2.kt @@ -0,0 +1,55 @@ +package nl.jolanrensen.example + +interface MathH2 { + + /** + * Computes the cosine of the angle [x] given in degrees. + * + * Special cases: + * - `cos(NaN|+Inf|-Inf)` is `NaN` + * + * @param x the angle in degrees + * @return the cosine of the angle [x] + */ + fun cos(x: Double): Double + + /** @include [cos] */ + fun cos(x: Float): Double + + /** @include [cos] */ + fun cos(x: Int): Double + + /** + * Computes the sine of the angle [x] given in degrees {@comment Oh no! I mean radians!}. + * + * Special cases: + * - `sin(NaN|+Inf|-Inf)` is `NaN` + * + * @param x the angle in degrees + * @return the sine of the angle [x] + */ + fun sin(x: Double): Double + + /** @include [sin] */ + fun sin(x: Float): Double + + /** @include [sin] */ + fun sin(x: Int): Double + + /** + * Computes the tangent of the angle [x] given in degrees. + * + * Special cases: + * - `tan(NaN|+Inf|-Inf)` is `NaN` + * + * @param x the angle in degrees + * @return the tangent of the angle [x] + */ + fun tan(x: Double): Double + + /** @include [tan] */ + fun tan(x: Float): Double + + /** @include [tan] */ + fun tan(x: Int): Double +} diff --git a/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH3.kt b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH3.kt new file mode 100644 index 00000000..934b5673 --- /dev/null +++ b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH3.kt @@ -0,0 +1,54 @@ +package nl.jolanrensen.example + +interface MathH3 { + + /** + * Computes the {@get OP} of the angle [x] given in degrees. + * + * Special cases: + * - `{@get FUN}(NaN|+Inf|-Inf)` is `NaN` + * + * @param x the angle in degrees + * @return the {@get OP} of the angle [x] + */ + private interface CosSinTanDocs + + /** + * @include [CosSinTanDocs] + * @set OP cosine + * @set FUN cos + */ + fun cos(x: Double): Double + + /** @include [cos] */ + fun cos(x: Float): Double + + /** @include [cos] */ + fun cos(x: Int): Double + + /** + * @include [CosSinTanDocs] + * @set OP sine + * @set FUN sin + */ + fun sin(x: Double): Double + + /** @include [sin] */ + fun sin(x: Float): Double + + /** @include [sin] */ + fun sin(x: Int): Double + + /** + * @include [CosSinTanDocs] + * @set OP tangent + * @set FUN tan + */ + fun tan(x: Double): Double + + /** @include [tan] */ + fun tan(x: Float): Double + + /** @include [tan] */ + fun tan(x: Int): Double +} diff --git a/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH.kt b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH4.kt similarity index 62% rename from kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH.kt rename to kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH4.kt index 7db1d149..64007fac 100644 --- a/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH.kt +++ b/kodex-example-gradle-project-jvm/src/main/kotlin/nl/jolanrensen/example/MathH4.kt @@ -5,18 +5,23 @@ package nl.jolanrensen.example */ /** - * Computes the {@get OP} of the angle [x] given in radians. + * Gradle plugin end results are stored at `/build/kodex` * - * Special cases: - * - `{@get FUN}(NaN|+Inf|-Inf)` is `NaN` - * - * @param x the angle in radians - * @return the {@get OP} of the angle [x] + * In most cases we can even use the Gradle plugin to generate a jar and sources-jar for us. */ -@ExcludeFromSources -private interface CosSinTanDocs - -interface MathH { +interface MathH4 { + + /** + * Computes the {@get OP} of the angle [x] given in radians. + * + * Special cases: + * - `{@get FUN}(NaN|+Inf|-Inf)` is `NaN` + * + * @param x the angle in radians + * @return the {@get OP} of the angle [x] + */ + @ExcludeFromSources + private interface CosSinTanDocs /** @include [CosSinTanDocs] {@set OP cosine} {@set FUN cos} */ fun cos(x: Double): Double diff --git a/kodex-example-gradle-project-multiplatform/.gradle/8.5/checksums/checksums.lock b/kodex-example-gradle-project-multiplatform/.gradle/8.5/checksums/checksums.lock index 1d6f65cab4b6d89e9f6e80db7879bf76a6f7e852..ec508357eeac3e0bcf068ab99ab4b8cf1bd977cb 100644 GIT binary patch literal 17 UcmZS1_DNZ~SMHq)$ literal 17 UcmZS1_DNZ~SM1p8VO%*wy7>G6NW}-2_rb#y~Px# diff --git a/kodex-example-gradle-project-multiplatform/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/kodex-example-gradle-project-multiplatform/.gradle/buildOutputCleanup/buildOutputCleanup.lock index fe21ee6ee166fac08f7b34d44ebb0f108866dcfe..7b7558653361d9b9c3c277995688a06c347a5766 100644 GIT binary patch literal 17 VcmZSnH}UrpzKIK>7{Gwh5CA_h1pNR2 literal 17 VcmZSnH}UrpzKIK>7{Gv03jjYV1oi*` diff --git a/kodex-example-gradle-project-multiplatform/.gradle/buildOutputCleanup/outputFiles.bin b/kodex-example-gradle-project-multiplatform/.gradle/buildOutputCleanup/outputFiles.bin index b352727b7dc4955c096a6220657fbadc3664a4ec..76eefae0b2011e29b601e3b7dcd22feab7373530 100644 GIT binary patch delta 141 zcmaFAp7G=c#tkMCj88V3N@Oq!Ot^VW>r>hRAqFsrFrPeC@+5!4!Q~-=vTaZ?#?7Hp zD>wvLqfcvmT68T4A{zdF@mD2Q0sFavWhYu>ETKwOH@{V1$imMg8hpPzvkEFGJh@e8 a5tC@)M#UfE8x2-4ZFcln$3IyU