From 4987cbdc8984ec683aff426dc5e65c86dee779a6 Mon Sep 17 00:00:00 2001 From: Nikita Lipsky Date: Thu, 8 Dec 2022 16:20:33 +0200 Subject: [PATCH] Move CodeViewer to KMM structure + add iOS target (#2544) --- examples/codeviewer/build.gradle.kts | 1 + experimental/examples/codeviewer/.gitignore | 14 +- .../examples/codeviewer/.run/desktop.run.xml | 21 - .../codeviewer/.run/desktopApp.run.xml | 28 ++ .../examples/codeviewer/.run/iosApp.run.xml | 8 + .../examples/codeviewer/.run/iosApp_.run.xml | 7 + experimental/examples/codeviewer/README.md | 27 +- .../codeviewer/android/build.gradle.kts | 26 -- .../codeviewer/androidApp/build.gradle.kts | 33 ++ .../src/main/AndroidManifest.xml | 0 .../src/main/assets/data/EditorView.kt | 0 .../org/jetbrains/codeviewer/MainActivity.kt | 2 +- .../res/drawable/ic_launcher_foreground.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../res/values/ic_launcher_background.xml | 0 .../src/main/res/values/strings.xml | 0 .../examples/codeviewer/build.gradle.kts | 1 + .../codeviewer/common/build.gradle.kts | 50 --- .../jetbrains/codeviewer/platform/Mouse.kt | 10 - .../{desktop => desktopApp}/build.gradle.kts | 6 +- .../kotlin/org/jetbrains/codeviewer/main.kt | 2 +- .../src/jvmMain/resources/ic_launcher.png | Bin .../examples/codeviewer/gradle.properties | 35 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 60756 bytes experimental/examples/codeviewer/gradlew | 263 +++++++----- experimental/examples/codeviewer/gradlew.bat | 37 +- .../Codeviewer.xcodeproj/project.pbxproj | 398 ++++++++++++++++++ .../iosApp/Configuration/TeamId.xcconfig | 1 + .../examples/codeviewer/iosApp/Podfile | 5 + .../codeviewer/iosApp/iosApp/Info.plist | 48 +++ .../codeviewer/iosApp/iosApp/iosApp.swift | 15 + .../codeviewer/run-configurations.png | Bin 0 -> 15762 bytes .../screenshots/desktop-run-configuration.png | Bin 2582 -> 0 bytes .../examples/codeviewer/settings.gradle.kts | 7 +- .../codeviewer/shared/build.gradle.kts | 78 ++++ .../src/androidMain/AndroidManifest.xml | 0 .../src/androidMain/kotlin/main.android.kt | 5 + .../org/jetbrains/codeviewer/platform/File.kt | 0 .../jetbrains/codeviewer/platform/Mouse.kt | 0 .../codeviewer/platform/Resources.kt | 0 .../codeviewer/platform/Scrollbar.kt | 0 .../org/jetbrains/codeviewer/platform/File.kt | 0 .../jetbrains/codeviewer/platform/Mouse.kt | 0 .../codeviewer/platform/Resources.kt | 2 +- .../codeviewer/platform/Scrollbar.kt | 4 +- .../org/jetbrains/codeviewer/ui/CodeViewer.kt | 0 .../jetbrains/codeviewer/ui/CodeViewerView.kt | 2 +- .../org/jetbrains/codeviewer/ui/MainView.kt | 2 +- .../jetbrains/codeviewer/ui/common/Fonts.kt | 2 +- .../codeviewer/ui/common/Settings.kt | 0 .../jetbrains/codeviewer/ui/common/Theme.kt | 0 .../jetbrains/codeviewer/ui/editor/Editor.kt | 0 .../codeviewer/ui/editor/EditorEmptyView.kt | 2 +- .../codeviewer/ui/editor/EditorTabsView.kt | 4 +- .../codeviewer/ui/editor/EditorView.kt | 2 +- .../jetbrains/codeviewer/ui/editor/Editors.kt | 0 .../codeviewer/ui/filetree/FileTree.kt | 0 .../codeviewer/ui/filetree/FileTreeView.kt | 4 +- .../codeviewer/ui/statusbar/StatusBar.kt | 2 +- .../codeviewer/util/LayoutModifiers.kt | 0 .../org/jetbrains/codeviewer/util/Loadable.kt | 4 +- .../codeviewer/util/SingleSelection.kt | 0 .../jetbrains/codeviewer/util/TextLines.kt | 0 .../codeviewer/util/VerticalSplittable.kt | 4 +- .../resources/font/jetbrainsmono_bold.ttf | Bin .../font/jetbrainsmono_bold_italic.ttf | Bin .../font/jetbrainsmono_extrabold.ttf | Bin .../font/jetbrainsmono_extrabold_italic.ttf | Bin .../resources/font/jetbrainsmono_italic.ttf | Bin .../resources/font/jetbrainsmono_medium.ttf | Bin .../font/jetbrainsmono_medium_italic.ttf | Bin .../resources/font/jetbrainsmono_regular.ttf | Bin .../src/desktopMain/kotlin/main.desktop.kt | 5 + .../org/jetbrains/codeviewer/platform/File.kt | 0 .../jetbrains/codeviewer/platform/Mouse.kt | 5 + .../codeviewer/platform/Resources.kt | 0 .../codeviewer/platform/Scrollbar.kt | 0 .../shared/src/iosMain/kotlin/main.ios.kt | 4 +- .../org/jetbrains/codeviewer/platform/File.kt | 41 ++ .../jetbrains/codeviewer/platform/Mouse.kt | 5 + .../codeviewer/platform/Resources.kt | 23 + .../codeviewer/platform/Scrollbar.kt | 18 + .../src/iosMain/resources/EditorView.kt | 183 ++++++++ .../jetbrains/codeviewer/platform/JvmFile.kt | 0 85 files changed, 1150 insertions(+), 296 deletions(-) delete mode 100644 experimental/examples/codeviewer/.run/desktop.run.xml create mode 100644 experimental/examples/codeviewer/.run/desktopApp.run.xml create mode 100644 experimental/examples/codeviewer/.run/iosApp.run.xml create mode 100644 experimental/examples/codeviewer/.run/iosApp_.run.xml delete mode 100644 experimental/examples/codeviewer/android/build.gradle.kts create mode 100644 experimental/examples/codeviewer/androidApp/build.gradle.kts rename experimental/examples/codeviewer/{android => androidApp}/src/main/AndroidManifest.xml (100%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/assets/data/EditorView.kt (100%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/java/org/jetbrains/codeviewer/MainActivity.kt (95%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/res/drawable/ic_launcher_foreground.xml (100%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/res/values/ic_launcher_background.xml (100%) rename experimental/examples/codeviewer/{android => androidApp}/src/main/res/values/strings.xml (100%) delete mode 100644 experimental/examples/codeviewer/common/build.gradle.kts delete mode 100644 experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt rename experimental/examples/codeviewer/{desktop => desktopApp}/build.gradle.kts (82%) rename experimental/examples/codeviewer/{desktop => desktopApp}/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt (92%) rename experimental/examples/codeviewer/{desktop => desktopApp}/src/jvmMain/resources/ic_launcher.png (100%) create mode 100644 experimental/examples/codeviewer/iosApp/Codeviewer.xcodeproj/project.pbxproj create mode 100644 experimental/examples/codeviewer/iosApp/Configuration/TeamId.xcconfig create mode 100644 experimental/examples/codeviewer/iosApp/Podfile create mode 100644 experimental/examples/codeviewer/iosApp/iosApp/Info.plist create mode 100644 experimental/examples/codeviewer/iosApp/iosApp/iosApp.swift create mode 100644 experimental/examples/codeviewer/run-configurations.png delete mode 100644 experimental/examples/codeviewer/screenshots/desktop-run-configuration.png create mode 100644 experimental/examples/codeviewer/shared/build.gradle.kts rename experimental/examples/codeviewer/{common => shared}/src/androidMain/AndroidManifest.xml (100%) create mode 100644 experimental/examples/codeviewer/shared/src/androidMain/kotlin/main.android.kt rename experimental/examples/codeviewer/{common => shared}/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/File.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/File.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt (71%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt (83%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/CodeViewer.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/CodeViewerView.kt (98%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/MainView.kt (97%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/common/Fonts.kt (96%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/common/Settings.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/common/Theme.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/Editor.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorEmptyView.kt (94%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorTabsView.kt (93%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorView.kt (98%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/Editors.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/filetree/FileTree.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/filetree/FileTreeView.kt (97%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/statusbar/StatusBar.kt (96%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/util/LayoutModifiers.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/util/Loadable.kt (78%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/util/SingleSelection.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/util/TextLines.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt (98%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_bold.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_bold_italic.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_extrabold.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_extrabold_italic.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_italic.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_medium.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_medium_italic.ttf (100%) rename experimental/examples/codeviewer/{common => shared}/src/commonMain/resources/font/jetbrainsmono_regular.ttf (100%) create mode 100644 experimental/examples/codeviewer/shared/src/desktopMain/kotlin/main.desktop.kt rename experimental/examples/codeviewer/{common => shared}/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/File.kt (100%) create mode 100644 experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt rename experimental/examples/codeviewer/{common => shared}/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt (100%) rename experimental/examples/codeviewer/{common => shared}/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt (100%) rename experimental/examples/{widgets-gallery => codeviewer}/shared/src/iosMain/kotlin/main.ios.kt (89%) create mode 100644 experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/File.kt create mode 100644 experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt create mode 100644 experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt create mode 100644 experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt create mode 100644 experimental/examples/codeviewer/shared/src/iosMain/resources/EditorView.kt rename experimental/examples/codeviewer/{common => shared}/src/jvmMain/kotlin/org/jetbrains/codeviewer/platform/JvmFile.kt (100%) diff --git a/examples/codeviewer/build.gradle.kts b/examples/codeviewer/build.gradle.kts index 0c00883af5..8d0c1f3d7c 100644 --- a/examples/codeviewer/build.gradle.kts +++ b/examples/codeviewer/build.gradle.kts @@ -14,5 +14,6 @@ allprojects { google() mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + mavenLocal() } } diff --git a/experimental/examples/codeviewer/.gitignore b/experimental/examples/codeviewer/.gitignore index ba8435b9c5..e949f25f51 100644 --- a/experimental/examples/codeviewer/.gitignore +++ b/experimental/examples/codeviewer/.gitignore @@ -2,14 +2,14 @@ .gradle /local.properties /.idea -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml .DS_Store build/ /captures .externalNativeBuild -.cxx \ No newline at end of file +.cxx +iosApp/Podfile.lock +iosApp/Pods/* +iosApp/Codeviewer.xcworkspace/* +iosApp/Codeviewer.xcodeproj/* +!iosApp/Codeviewer.xcodeproj/project.pbxproj +shared/shared.podspec diff --git a/experimental/examples/codeviewer/.run/desktop.run.xml b/experimental/examples/codeviewer/.run/desktop.run.xml deleted file mode 100644 index d9335c1be5..0000000000 --- a/experimental/examples/codeviewer/.run/desktop.run.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/experimental/examples/codeviewer/.run/desktopApp.run.xml b/experimental/examples/codeviewer/.run/desktopApp.run.xml new file mode 100644 index 0000000000..2d56d7f072 --- /dev/null +++ b/experimental/examples/codeviewer/.run/desktopApp.run.xml @@ -0,0 +1,28 @@ + + + + + + + + true + true + false + + + \ No newline at end of file diff --git a/experimental/examples/codeviewer/.run/iosApp.run.xml b/experimental/examples/codeviewer/.run/iosApp.run.xml new file mode 100644 index 0000000000..cb9a3578f1 --- /dev/null +++ b/experimental/examples/codeviewer/.run/iosApp.run.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/experimental/examples/codeviewer/.run/iosApp_.run.xml b/experimental/examples/codeviewer/.run/iosApp_.run.xml new file mode 100644 index 0000000000..b8737d8dd8 --- /dev/null +++ b/experimental/examples/codeviewer/.run/iosApp_.run.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/experimental/examples/codeviewer/README.md b/experimental/examples/codeviewer/README.md index 172adda0ce..6a5b097c67 100644 --- a/experimental/examples/codeviewer/README.md +++ b/experimental/examples/codeviewer/README.md @@ -1,10 +1,22 @@ -MPP Code Viewer example for desktop/android written in Multiplatform Compose library. +# Code Viewer +MPP Code Viewer example for desktop/android/iOS written in Multiplatform Compose library. -### Running desktop application +## How to run -* To run, launch command: `./gradlew :desktop:run` -* Or choose **desktop** configuration in IDE and run it. - ![desktop-run-configuration.png](screenshots/desktop-run-configuration.png) +Choose a run configuration for an appropriate target in IDE and run it. + +![run-configurations.png](run-configurations.png) + +To run on iOS device, please correct `iosApp/Configuration/TeamId.xcconfig` with your Apple Team ID. +Alternatively, you may setup signing within XCode opening `iosApp/Codeviewer.xcworkspace` and then +using "Signing & Capabilities" tab of `Codeviewer` target. + +Then choose **iosApp** configuration in IDE and run it +(may also be referred as `Codeviewer` in the Run Configurations or `iosApp_` for Android studio). + +## Run on desktop via Gradle + +`./gradlew desktopApp:run` ### Building native desktop distribution ``` @@ -12,9 +24,4 @@ MPP Code Viewer example for desktop/android written in Multiplatform Compose lib # outputs are written to desktop/build/compose/binaries ``` -### Installing Android application on device/emulator -``` -./gradlew installDebug -``` - ![Desktop](screenshots/codeviewer.png) \ No newline at end of file diff --git a/experimental/examples/codeviewer/android/build.gradle.kts b/experimental/examples/codeviewer/android/build.gradle.kts deleted file mode 100644 index 13073d45fb..0000000000 --- a/experimental/examples/codeviewer/android/build.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -plugins { - id("com.android.application") - kotlin("android") - id("org.jetbrains.compose") -} - -android { - compileSdk = 32 - - defaultConfig { - minSdk = 26 - targetSdk = 32 - versionCode = 1 - versionName = "1.0" - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } -} - -dependencies { - implementation(project(":common")) - implementation("androidx.activity:activity-compose:1.5.0") -} \ No newline at end of file diff --git a/experimental/examples/codeviewer/androidApp/build.gradle.kts b/experimental/examples/codeviewer/androidApp/build.gradle.kts new file mode 100644 index 0000000000..b65e1126a2 --- /dev/null +++ b/experimental/examples/codeviewer/androidApp/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + kotlin("multiplatform") + id("com.android.application") + id("org.jetbrains.compose") +} + +kotlin { + android() + sourceSets { + val androidMain by getting { + dependencies { + implementation(project(":shared")) + implementation("androidx.appcompat:appcompat:1.5.1") + implementation("androidx.activity:activity-compose:1.6.1") + } + } + } +} + +android { + compileSdk = 33 + defaultConfig { + applicationId = "org.jetbrains.Codeviewer" + minSdk = 24 + targetSdk = 33 + versionCode = 1 + versionName = "1.0" + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} diff --git a/experimental/examples/codeviewer/android/src/main/AndroidManifest.xml b/experimental/examples/codeviewer/androidApp/src/main/AndroidManifest.xml similarity index 100% rename from experimental/examples/codeviewer/android/src/main/AndroidManifest.xml rename to experimental/examples/codeviewer/androidApp/src/main/AndroidManifest.xml diff --git a/experimental/examples/codeviewer/android/src/main/assets/data/EditorView.kt b/experimental/examples/codeviewer/androidApp/src/main/assets/data/EditorView.kt similarity index 100% rename from experimental/examples/codeviewer/android/src/main/assets/data/EditorView.kt rename to experimental/examples/codeviewer/androidApp/src/main/assets/data/EditorView.kt diff --git a/experimental/examples/codeviewer/android/src/main/java/org/jetbrains/codeviewer/MainActivity.kt b/experimental/examples/codeviewer/androidApp/src/main/java/org/jetbrains/codeviewer/MainActivity.kt similarity index 95% rename from experimental/examples/codeviewer/android/src/main/java/org/jetbrains/codeviewer/MainActivity.kt rename to experimental/examples/codeviewer/androidApp/src/main/java/org/jetbrains/codeviewer/MainActivity.kt index 872c04c87a..850c63ef7d 100644 --- a/experimental/examples/codeviewer/android/src/main/java/org/jetbrains/codeviewer/MainActivity.kt +++ b/experimental/examples/codeviewer/androidApp/src/main/java/org/jetbrains/codeviewer/MainActivity.kt @@ -4,7 +4,7 @@ import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import org.jetbrains.codeviewer.platform._HomeFolder -import org.jetbrains.codeviewer.ui.MainView +import MainView import java.io.File import java.io.FileOutputStream diff --git a/experimental/examples/codeviewer/android/src/main/res/drawable/ic_launcher_foreground.xml b/experimental/examples/codeviewer/androidApp/src/main/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from experimental/examples/codeviewer/android/src/main/res/drawable/ic_launcher_foreground.xml rename to experimental/examples/codeviewer/androidApp/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/experimental/examples/codeviewer/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/experimental/examples/codeviewer/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from experimental/examples/codeviewer/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to experimental/examples/codeviewer/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/experimental/examples/codeviewer/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/experimental/examples/codeviewer/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from experimental/examples/codeviewer/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to experimental/examples/codeviewer/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/experimental/examples/codeviewer/android/src/main/res/values/ic_launcher_background.xml b/experimental/examples/codeviewer/androidApp/src/main/res/values/ic_launcher_background.xml similarity index 100% rename from experimental/examples/codeviewer/android/src/main/res/values/ic_launcher_background.xml rename to experimental/examples/codeviewer/androidApp/src/main/res/values/ic_launcher_background.xml diff --git a/experimental/examples/codeviewer/android/src/main/res/values/strings.xml b/experimental/examples/codeviewer/androidApp/src/main/res/values/strings.xml similarity index 100% rename from experimental/examples/codeviewer/android/src/main/res/values/strings.xml rename to experimental/examples/codeviewer/androidApp/src/main/res/values/strings.xml diff --git a/experimental/examples/codeviewer/build.gradle.kts b/experimental/examples/codeviewer/build.gradle.kts index 0c00883af5..8d0c1f3d7c 100644 --- a/experimental/examples/codeviewer/build.gradle.kts +++ b/experimental/examples/codeviewer/build.gradle.kts @@ -14,5 +14,6 @@ allprojects { google() mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + mavenLocal() } } diff --git a/experimental/examples/codeviewer/common/build.gradle.kts b/experimental/examples/codeviewer/common/build.gradle.kts deleted file mode 100644 index 1b8e451301..0000000000 --- a/experimental/examples/codeviewer/common/build.gradle.kts +++ /dev/null @@ -1,50 +0,0 @@ -plugins { - id("com.android.library") - kotlin("multiplatform") - id("org.jetbrains.compose") -} - -kotlin { - android() - jvm("desktop") - - sourceSets { - named("commonMain") { - dependencies { - api(compose.runtime) - api(compose.foundation) - api(compose.material) - api(compose.materialIconsExtended) - } - } - named("androidMain") { - kotlin.srcDirs("src/jvmMain/kotlin") - dependencies { - api("androidx.appcompat:appcompat:1.5.1") - api("androidx.core:core-ktx:1.8.0") - } - } - named("desktopMain") { - kotlin.srcDirs("src/jvmMain/kotlin") - dependencies { - api(compose.desktop.common) - } - } - } -} - -android { - compileSdk = 32 - - defaultConfig { - minSdk = 26 - targetSdk = 32 - } - - sourceSets { - named("main") { - manifest.srcFile("src/androidMain/AndroidManifest.xml") - res.srcDirs("src/androidMain/res", "src/commonMain/resources") - } - } -} diff --git a/experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt b/experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt deleted file mode 100644 index 7726dbb3e7..0000000000 --- a/experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.jetbrains.codeviewer.platform - -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.pointer.PointerIcon -import androidx.compose.ui.input.pointer.pointerHoverIcon -import java.awt.Cursor - -actual fun Modifier.cursorForHorizontalResize(): Modifier = - this.pointerHoverIcon(PointerIcon(Cursor(Cursor.E_RESIZE_CURSOR))) diff --git a/experimental/examples/codeviewer/desktop/build.gradle.kts b/experimental/examples/codeviewer/desktopApp/build.gradle.kts similarity index 82% rename from experimental/examples/codeviewer/desktop/build.gradle.kts rename to experimental/examples/codeviewer/desktopApp/build.gradle.kts index e7263fd745..240574ab9e 100644 --- a/experimental/examples/codeviewer/desktop/build.gradle.kts +++ b/experimental/examples/codeviewer/desktopApp/build.gradle.kts @@ -1,17 +1,17 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { - kotlin("multiplatform") // kotlin("jvm") doesn't work well in IDEA/AndroidStudio (https://github.com/JetBrains/compose-jb/issues/22) + kotlin("multiplatform") id("org.jetbrains.compose") } kotlin { jvm {} sourceSets { - named("jvmMain") { + val jvmMain by getting { dependencies { implementation(compose.desktop.currentOs) - implementation(project(":common")) + implementation(project(":shared")) } } } diff --git a/experimental/examples/codeviewer/desktop/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt b/experimental/examples/codeviewer/desktopApp/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt similarity index 92% rename from experimental/examples/codeviewer/desktop/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt rename to experimental/examples/codeviewer/desktopApp/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt index b3e70a808f..cfe2817302 100644 --- a/experimental/examples/codeviewer/desktop/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt +++ b/experimental/examples/codeviewer/desktopApp/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt @@ -6,7 +6,7 @@ import androidx.compose.ui.res.useResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.WindowState import androidx.compose.ui.window.singleWindowApplication -import org.jetbrains.codeviewer.ui.MainView +import MainView fun main() = singleWindowApplication( title = "Code Viewer", diff --git a/experimental/examples/codeviewer/desktop/src/jvmMain/resources/ic_launcher.png b/experimental/examples/codeviewer/desktopApp/src/jvmMain/resources/ic_launcher.png similarity index 100% rename from experimental/examples/codeviewer/desktop/src/jvmMain/resources/ic_launcher.png rename to experimental/examples/codeviewer/desktopApp/src/jvmMain/resources/ic_launcher.png diff --git a/experimental/examples/codeviewer/gradle.properties b/experimental/examples/codeviewer/gradle.properties index c18fa7d46c..ea83c74d6a 100644 --- a/experimental/examples/codeviewer/gradle.properties +++ b/experimental/examples/codeviewer/gradle.properties @@ -1,24 +1,17 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app"s APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true -# Automatically convert third-party libraries to use AndroidX -android.enableJetifier=true -# Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official +xcodeproj=./iosApp +kotlin.native.cocoapods.generate.wrapper=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx3g +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.uikit.enabled=true +kotlin.native.cacheKind=none +kotlin.native.useEmbeddableCompilerJar=true +kotlin.native.enableDependencyPropagation=false +kotlin.mpp.enableGranularSourceSetsMetadata=true +# Enable kotlin/native experimental memory model +kotlin.native.binary.memoryModel=experimental kotlin.version=1.7.20 agp.version=7.1.3 -compose.version=1.2.1 +compose.version=1.3.0-beta04-dev885 diff --git a/experimental/examples/codeviewer/gradle/wrapper/gradle-wrapper.jar b/experimental/examples/codeviewer/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 21827 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 D86?w= diff --git a/experimental/examples/codeviewer/gradlew b/experimental/examples/codeviewer/gradlew index 2fe81a7d95..a69d9cb6c2 100755 --- a/experimental/examples/codeviewer/gradlew +++ b/experimental/examples/codeviewer/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,79 +140,101 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/experimental/examples/codeviewer/gradlew.bat b/experimental/examples/codeviewer/gradlew.bat index 9618d8d960..f127cfd49d 100644 --- a/experimental/examples/codeviewer/gradlew.bat +++ b/experimental/examples/codeviewer/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,13 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +64,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/experimental/examples/codeviewer/iosApp/Codeviewer.xcodeproj/project.pbxproj b/experimental/examples/codeviewer/iosApp/Codeviewer.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..df3eca3e08 --- /dev/null +++ b/experimental/examples/codeviewer/iosApp/Codeviewer.xcodeproj/project.pbxproj @@ -0,0 +1,398 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 2152FB042600AC8F00CF470E /* iosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iosApp.swift */; }; + C1FC908188C4E8695729CB06 /* Pods_Codeviewer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DE96E47030356CE6AD9794A /* Pods_Codeviewer.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1EB65E27D2C0F884D0A1A133 /* Pods-Codeviewer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Codeviewer.debug.xcconfig"; path = "Target Support Files/Pods-Codeviewer/Pods-Codeviewer.debug.xcconfig"; sourceTree = ""; }; + 2152FB032600AC8F00CF470E /* iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosApp.swift; sourceTree = ""; }; + 3D7A606AB0AD7636269BD9D0 /* Pods-Codeviewer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Codeviewer.release.xcconfig"; path = "Target Support Files/Pods-Codeviewer/Pods-Codeviewer.release.xcconfig"; sourceTree = ""; }; + 7555FF7B242A565900829871 /* Codeviewer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Codeviewer.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8DE96E47030356CE6AD9794A /* Pods_Codeviewer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Codeviewer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + AB3632DC29227652001CCB65 /* TeamId.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TeamId.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9964867F0862B4D9FB6ABFC7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C1FC908188C4E8695729CB06 /* Pods_Codeviewer.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7555FF72242A565900829871 = { + isa = PBXGroup; + children = ( + AB1DB47929225F7C00F7AF9C /* Configuration */, + 7555FF7D242A565900829871 /* iosApp */, + 7555FF7C242A565900829871 /* Products */, + E1DAFBE8E1CFC0878361EF0E /* Pods */, + B62309C7396AD7BF607A63B2 /* Frameworks */, + ); + sourceTree = ""; + }; + 7555FF7C242A565900829871 /* Products */ = { + isa = PBXGroup; + children = ( + 7555FF7B242A565900829871 /* Codeviewer.app */, + ); + name = Products; + sourceTree = ""; + }; + 7555FF7D242A565900829871 /* iosApp */ = { + isa = PBXGroup; + children = ( + 7555FF8C242A565B00829871 /* Info.plist */, + 2152FB032600AC8F00CF470E /* iosApp.swift */, + ); + path = iosApp; + sourceTree = ""; + }; + AB1DB47929225F7C00F7AF9C /* Configuration */ = { + isa = PBXGroup; + children = ( + AB3632DC29227652001CCB65 /* TeamId.xcconfig */, + ); + path = Configuration; + sourceTree = ""; + }; + B62309C7396AD7BF607A63B2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8DE96E47030356CE6AD9794A /* Pods_Codeviewer.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E1DAFBE8E1CFC0878361EF0E /* Pods */ = { + isa = PBXGroup; + children = ( + 1EB65E27D2C0F884D0A1A133 /* Pods-Codeviewer.debug.xcconfig */, + 3D7A606AB0AD7636269BD9D0 /* Pods-Codeviewer.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7555FF7A242A565900829871 /* Codeviewer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "Codeviewer" */; + buildPhases = ( + E8D673591E7196AEA2EA10E2 /* [CP] Check Pods Manifest.lock */, + 7555FF77242A565900829871 /* Sources */, + 7555FF79242A565900829871 /* Resources */, + 9964867F0862B4D9FB6ABFC7 /* Frameworks */, + 36D9E9FD1C89A17F9A69F669 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Codeviewer; + productName = iosApp; + productReference = 7555FF7B242A565900829871 /* Codeviewer.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7555FF73242A565900829871 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = org.jetbrains; + TargetAttributes = { + 7555FF7A242A565900829871 = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "Codeviewer" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7555FF72242A565900829871; + productRefGroup = 7555FF7C242A565900829871 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7555FF7A242A565900829871 /* Codeviewer */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7555FF79242A565900829871 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 36D9E9FD1C89A17F9A69F669 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Codeviewer/Pods-Codeviewer-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Codeviewer/Pods-Codeviewer-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Codeviewer/Pods-Codeviewer-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + E8D673591E7196AEA2EA10E2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Codeviewer-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7555FF77242A565900829871 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2152FB042600AC8F00CF470E /* iosApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7555FFA3242A565B00829871 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB3632DC29227652001CCB65 /* TeamId.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7555FFA4242A565B00829871 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB3632DC29227652001CCB65 /* TeamId.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7555FFA6242A565B00829871 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1EB65E27D2C0F884D0A1A133 /* Pods-Codeviewer.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = ""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = iosApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.jetbrains.Codeviewer${TEAM_ID}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7555FFA7242A565B00829871 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3D7A606AB0AD7636269BD9D0 /* Pods-Codeviewer.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = ""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = iosApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.jetbrains.Codeviewer${TEAM_ID}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7555FF76242A565900829871 /* Build configuration list for PBXProject "Codeviewer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7555FFA3242A565B00829871 /* Debug */, + 7555FFA4242A565B00829871 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "Codeviewer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7555FFA6242A565B00829871 /* Debug */, + 7555FFA7242A565B00829871 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7555FF73242A565900829871 /* Project object */; +} diff --git a/experimental/examples/codeviewer/iosApp/Configuration/TeamId.xcconfig b/experimental/examples/codeviewer/iosApp/Configuration/TeamId.xcconfig new file mode 100644 index 0000000000..bf06eb27e9 --- /dev/null +++ b/experimental/examples/codeviewer/iosApp/Configuration/TeamId.xcconfig @@ -0,0 +1 @@ +TEAM_ID= diff --git a/experimental/examples/codeviewer/iosApp/Podfile b/experimental/examples/codeviewer/iosApp/Podfile new file mode 100644 index 0000000000..d2bd79b172 --- /dev/null +++ b/experimental/examples/codeviewer/iosApp/Podfile @@ -0,0 +1,5 @@ +target 'Codeviewer' do + use_frameworks! + platform :ios, '14.1' + pod 'shared', :path => '../shared' +end \ No newline at end of file diff --git a/experimental/examples/codeviewer/iosApp/iosApp/Info.plist b/experimental/examples/codeviewer/iosApp/iosApp/Info.plist new file mode 100644 index 0000000000..9a269f5eaa --- /dev/null +++ b/experimental/examples/codeviewer/iosApp/iosApp/Info.plist @@ -0,0 +1,48 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + + UILaunchScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/experimental/examples/codeviewer/iosApp/iosApp/iosApp.swift b/experimental/examples/codeviewer/iosApp/iosApp/iosApp.swift new file mode 100644 index 0000000000..b42016a6fc --- /dev/null +++ b/experimental/examples/codeviewer/iosApp/iosApp/iosApp.swift @@ -0,0 +1,15 @@ +import UIKit +import shared + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + let mainViewController = Main_iosKt.MainViewController() + window?.rootViewController = mainViewController + window?.makeKeyAndVisible() + return true + } +} diff --git a/experimental/examples/codeviewer/run-configurations.png b/experimental/examples/codeviewer/run-configurations.png new file mode 100644 index 0000000000000000000000000000000000000000..0840602f9be0b88523fb8597515424944a440e2f GIT binary patch literal 15762 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 literal 0 HcmV?d00001 diff --git a/experimental/examples/codeviewer/screenshots/desktop-run-configuration.png b/experimental/examples/codeviewer/screenshots/desktop-run-configuration.png deleted file mode 100644 index 3688407c6f7e8c812047c17995d1042f8d378eb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2582 zcmV+x3hDKUP)%0{0a4H@cf z*;G|kL9goSYLR}uA?v9>U-Nbl@MFuR8*9qUQ$deVY*r?*Z+JuhB&lgT94onxf_=7{YejE|2;Mn;CdiZ-GbA}=pbT(PpUvfYjPe^xsP zqoboyUS6)hK1TFHG&D3IA|e766&3An)aRs{>KfEm*UDdQUG4jI)m2@0@eU#6MKGfG zqp`6Ok&%%WLs(n$AsE&W`~M~H6|MwdM`mF*>T2pxUt5PK$pLVTx{vb8@-7c2tPWw* zn>WbKFGQ9p9}SI7`prhP2}>a)7+Hlm_$l%(OeJ{=ih7G2$sE-y==@WIu*T62M;@O+ zc4033QUYOnX9o^?e22V}{4W0xtPWvbQ3=9glMomg2fxrL)TxxyS@1Dlc6K)2D1f^f z+=o@BCHwYuSPCIiVMakF);QT=&%@utTe(t2WretuzHN6^t<+fC0EZ}7eBrPeJ0Bdy zM(5r5oy#61f7zpnR*1mn!0*%x}>xWB&4PzJ==szH9pXXPjCcYrf2F`w~L~p zBFvjNPb&4UMt*)iX3d&~f`S75CIkfqAvZTyzxuO@?m+meAPej7?!;Q3vpBZK?Z*4Cn_sR>J#EWyp2H)UB1?U-#tb5TOkw(m~` z_o=I^lj5Qyaa(8Z+!GKI2I?!vt=OO(>c=n#ILjxibbGY}vA9m^^th_U_#) zQy7ek7cXMw%$d^m%$YNClL;T&m6er=ldfL98a_TgxN_wR1`HU0VZ(;u(xpqXKi3mX zw%@jGn>aAz{Q2|PwQCoaE?p|;!@fIv(}&J`_Uu_4K71I*jvf0zhYlUWg$ozt$Mvb` zNeC&z@#XC;k}^G#d{95_^tCUaX;I;_Skf9FE-!XC)%jeF^{=c zZDX77{VvLW`o21n#Sp$xHzg=CUdDQ1aWCMmoG&UdS=^5R62zxrF$%(9f$y$|uZ#_w zo167rp}4phW5(;Hq@#Dv3+&6sqa3m)u z3v2|pw6s)UV0%7+AYdAB{BDGb$KY~KP7cP583R{WSJ`L7h7H)XX_K_Iv$Mm{p+k|F zm?-^^A3q*9Zro^l${hyV9z1vu_V)JJy?eKa%SVqMmC66kqNgF$L@?-F$G!fH*sKJz z9ZD|(d`CIl7q>UVUV+W(xU#BJQmY8g9eYHpV{p1gzyHT%F@$N#0bNx3C2WK+ zMy1(+(CAhGe|5*F0%1r@k~n8a;o;#SV?Zr9SH5wg$z{rg+{WUN}XN}yxhx^+w3Rg09A6mdkRO}gTV6DL}?(c#vw zU*G!qQ$cX~gP@aAbivfrRDH7!!+H?f34|xS&mlHDvC9y$y{Y&$oMYYaozGvS0QyF` z;6Fot!i|W#xEbk;KdCV&9g@fUA?QEwNq%PbaV&z6F6bK^DR619@$bDh0BT~JsKgYN z&e}Vm79WF3OUEoC zJYV>sTqk`{rM!U{=KxQ?Pbi!g%V*d9#mY5rnLK-Ti`E$ANnH zBaE)^q4Ww2>vVpQX_pW=I5^0dZr{Fr7&vgCxEjZ4gyYepM{6n!;C&(LA#r#N(IVBydv0~sap(rdZYS+idWD$g=6_xn;$+LIGhblO{6=)ia5B;9Q zFC+?XK7mp#M<RYF!i5VF8yhQCD;C@8B!-o$sYSbv4J9kb#(}6ji!(-Cvv}ql> z7*qG6MT;ywSVLC ztyIeYR@L{lu-o{f&jmRy!FP#sSL4EXv!S;L!b@A*FVi+@ndZ;S@kaAJ7zBv@Xu;}~=hb!{LpyIRxScn%Z97iUXrWD+Xu;!X z$JB!9{qp6@az6U$8*4^)Ak-$SzjZ$WpOj}ZgJ4M|+>w}8lT69tbWHJtjVYIo$RdRz zm@I&_^(=y{nvUP93YV~Pl3I&u^@WQ{e|_T>#vUyy%5GrtyS+J loadable(load: () -> T): MutableState { +internal fun loadable(load: () -> T): MutableState { return loadableScoped { load() } } private val loadingKey = Any() @Composable -fun loadableScoped(load: CoroutineScope.() -> T): MutableState { +internal fun loadableScoped(load: CoroutineScope.() -> T): MutableState { val state: MutableState = remember { mutableStateOf(null) } LaunchedEffect(loadingKey) { try { diff --git a/experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/SingleSelection.kt b/experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/SingleSelection.kt similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/SingleSelection.kt rename to experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/SingleSelection.kt diff --git a/experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/TextLines.kt b/experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/TextLines.kt similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/TextLines.kt rename to experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/TextLines.kt diff --git a/experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt b/experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt similarity index 98% rename from experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt rename to experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt index d9b2e0f896..e3f415bcd0 100644 --- a/experimental/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt +++ b/experimental/examples/codeviewer/shared/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt @@ -22,7 +22,7 @@ import org.jetbrains.codeviewer.platform.cursorForHorizontalResize import org.jetbrains.codeviewer.ui.common.AppTheme @Composable -fun VerticalSplittable( +internal fun VerticalSplittable( modifier: Modifier, splitterState: SplitterState, onResize: (delta: Dp) -> Unit, @@ -57,7 +57,7 @@ class SplitterState { } @Composable -fun VerticalSplitter( +internal fun VerticalSplitter( splitterState: SplitterState, onResize: (delta: Dp) -> Unit, color: Color = AppTheme.colors.backgroundDark diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_bold.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_bold.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_bold.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_bold.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_bold_italic.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_bold_italic.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_bold_italic.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_bold_italic.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_extrabold.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_extrabold.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_extrabold.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_extrabold.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_extrabold_italic.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_extrabold_italic.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_extrabold_italic.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_extrabold_italic.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_italic.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_italic.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_italic.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_italic.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_medium.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_medium.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_medium.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_medium.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_medium_italic.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_medium_italic.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_medium_italic.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_medium_italic.ttf diff --git a/experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_regular.ttf b/experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_regular.ttf similarity index 100% rename from experimental/examples/codeviewer/common/src/commonMain/resources/font/jetbrainsmono_regular.ttf rename to experimental/examples/codeviewer/shared/src/commonMain/resources/font/jetbrainsmono_regular.ttf diff --git a/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/main.desktop.kt b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/main.desktop.kt new file mode 100644 index 0000000000..faa491aedf --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/main.desktop.kt @@ -0,0 +1,5 @@ +import androidx.compose.runtime.Composable +import org.jetbrains.codeviewer.ui.MainView + +@Composable +fun MainView() = MainView() \ No newline at end of file diff --git a/experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/File.kt b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/File.kt similarity index 100% rename from experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/File.kt rename to experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/File.kt diff --git a/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt new file mode 100644 index 0000000000..839576bb41 --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt @@ -0,0 +1,5 @@ +package org.jetbrains.codeviewer.platform + +import androidx.compose.ui.Modifier + +actual fun Modifier.cursorForHorizontalResize() = this diff --git a/experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt similarity index 100% rename from experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt rename to experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt diff --git a/experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt b/experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt similarity index 100% rename from experimental/examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt rename to experimental/examples/codeviewer/shared/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt diff --git a/experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/main.ios.kt b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/main.ios.kt similarity index 89% rename from experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/main.ios.kt rename to experimental/examples/codeviewer/shared/src/iosMain/kotlin/main.ios.kt index c64bf93623..1e3e239735 100644 --- a/experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/main.ios.kt +++ b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/main.ios.kt @@ -9,11 +9,11 @@ import androidx.compose.foundation.layout.height import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Application -import org.jetbrains.compose.demo.widgets.ui.MainView import platform.UIKit.UIViewController +import org.jetbrains.codeviewer.ui.MainView fun MainViewController() : UIViewController = - Application("Widgets Gallery") { + Application("Codeviewer") { Column { // To skip upper part of screen. Box( diff --git a/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/File.kt b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/File.kt new file mode 100644 index 0000000000..889ee767cb --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/File.kt @@ -0,0 +1,41 @@ +@file:Suppress("NewApi") + +package org.jetbrains.codeviewer.platform + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.runBlocking +import org.jetbrains.codeviewer.util.EmptyTextLines +import org.jetbrains.codeviewer.util.TextLines +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.resource + +class VirtualFile(override val name: String, override val isDirectory: Boolean, val textLines: TextLines, override val children: List = listOf()): File { + override val hasChildren: Boolean + get() = children.size > 0 + + override fun readLines(scope: CoroutineScope): TextLines = textLines +} + +fun ByteArray.toTextLines(): TextLines = object : TextLines { + val contents = decodeToString().split("\n") + + override val size: Int + get() = contents.size + + override fun get(index: Int): String = contents[index] +} + + +@OptIn(ExperimentalResourceApi::class) +actual val HomeFolder: File get() = VirtualFile("files", + isDirectory = true, + textLines = EmptyTextLines, + children = listOf( + VirtualFile("EditorView.kt", + isDirectory = false, + textLines = runBlocking { + resource("EditorView.kt").readBytes() + }.toTextLines() + ) + ) +) diff --git a/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt new file mode 100644 index 0000000000..3a8174f63c --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt @@ -0,0 +1,5 @@ +package org.jetbrains.codeviewer.platform + +import androidx.compose.ui.Modifier + +actual fun Modifier.cursorForHorizontalResize(): Modifier = this diff --git a/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt new file mode 100644 index 0000000000..6c63ae93af --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt @@ -0,0 +1,23 @@ +package org.jetbrains.codeviewer.platform + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import kotlinx.coroutines.runBlocking +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.resource + +private val cache: MutableMap = mutableMapOf() + +@OptIn(ExperimentalResourceApi::class) +@Composable +internal actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font { + return cache.getOrPut(res) { + val byteArray = runBlocking { + resource("font/$res.ttf").readBytes() + } + androidx.compose.ui.text.platform.Font(res, byteArray, weight, style) + } +} \ No newline at end of file diff --git a/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt new file mode 100644 index 0000000000..7ffe0d5b00 --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/iosMain/kotlin/org/jetbrains/codeviewer/platform/Scrollbar.kt @@ -0,0 +1,18 @@ +package org.jetbrains.codeviewer.platform + +import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +internal actual fun VerticalScrollbar( + modifier: Modifier, + scrollState: ScrollState +) = Unit + +@Composable +internal actual fun VerticalScrollbar( + modifier: Modifier, + scrollState: LazyListState +) = Unit \ No newline at end of file diff --git a/experimental/examples/codeviewer/shared/src/iosMain/resources/EditorView.kt b/experimental/examples/codeviewer/shared/src/iosMain/resources/EditorView.kt new file mode 100644 index 0000000000..90037570b1 --- /dev/null +++ b/experimental/examples/codeviewer/shared/src/iosMain/resources/EditorView.kt @@ -0,0 +1,183 @@ +/** + * This file is an example (we can open it in iOS application) + */ + +package org.jetbrains.codeviewer.ui.editor + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.selection.DisableSelection +import androidx.compose.material.AmbientContentColor +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.* +import androidx.compose.ui.unit.dp +import org.jetbrains.codeviewer.platform.SelectionContainer +import org.jetbrains.codeviewer.ui.common.AppTheme +import org.jetbrains.codeviewer.ui.common.Fonts +import org.jetbrains.codeviewer.ui.common.Settings +import org.jetbrains.codeviewer.util.loadableScoped +import org.jetbrains.codeviewer.util.withoutWidthConstraints +import kotlin.text.Regex.Companion.fromLiteral + +@Composable +fun EditorView(model: Editor, settings: Settings) = key(model) { + with (LocalDensity.current) { + SelectionContainer { + Surface( + Modifier.fillMaxSize(), + color = AppTheme.colors.backgroundDark, + ) { + val lines by loadableScoped(model.lines) + + if (lines != null) { + Box { + Lines(lines!!, settings) + Box( + Modifier + .offset( + x = settings.fontSize.toDp() * 0.5f * settings.maxLineSymbols + ) + .width(1.dp) + .fillMaxHeight() + .background(AppTheme.colors.backgroundLight) + ) + } + } else { + CircularProgressIndicator( + modifier = Modifier + .size(36.dp) + .padding(4.dp) + ) + } + } + } + } +} + +@Composable +private fun Lines(lines: Editor.Lines, settings: Settings) = with(DensityAmbient.current) { + val maxNumber = remember(lines.lineNumberDigitCount) { + (1..lines.lineNumberDigitCount).joinToString(separator = "") { "9" } + } + + Box(Modifier.fillMaxSize()) { + val scrollState = rememberLazyListState() + val lineHeight = settings.fontSize.toDp() * 1.6f + + LazyColumnFor( + lines.size, + modifier = Modifier.fillMaxSize(), + state = scrollState, + itemContent = { index -> + val line: Editor.Line? by loadable { lines.get(index) } + Box(Modifier.height(lineHeight)) { + if (line != null) { + Line(Modifier.align(Alignment.CenterStart), maxNumber, line!!, settings) + } + } + } + ) + + VerticalScrollbar( + Modifier.align(Alignment.CenterEnd), + scrollState, + lines.size, + lineHeight + ) + } +} + +// Поддержка русского языка +// دعم اللغة العربية +// 中文支持 +@Composable +private fun Line(modifier: Modifier, maxNumber: String, line: Editor.Line, settings: Settings) { + Row(modifier = modifier) { + DisableSelection { + Box { + LineNumber(maxNumber, Modifier.alpha(0f), settings) + LineNumber(line.number.toString(), Modifier.align(Alignment.CenterEnd), settings) + } + } + LineContent( + line.content, + modifier = Modifier + .weight(1f) + .withoutWidthConstraints() + .padding(start = 28.dp, end = 12.dp), + settings = settings + ) + } +} + +@Composable +private fun LineNumber(number: String, modifier: Modifier, settings: Settings) = Text( + text = number, + fontSize = settings.fontSize, + fontFamily = Fonts.jetbrainsMono(), + color = AmbientContentColor.current.copy(alpha = 0.30f), + modifier = modifier.padding(start = 12.dp) +) + +@Composable +private fun LineContent(content: Editor.Content, modifier: Modifier, settings: Settings) = Text( + text = if (content.isCode) { + codeString(content.value.value) + } else { + AnnotatedString(content.value.value) + }, + fontSize = settings.fontSize, + fontFamily = Fonts.jetbrainsMono(), + modifier = modifier, + softWrap = false +) + +private fun codeString(str: String) = buildAnnotatedString { + withStyle(AppTheme.code.simple) { + append(str.replace("\t", " ")) + addStyle(AppTheme.code.punctuation, ":") + addStyle(AppTheme.code.punctuation, "=") + addStyle(AppTheme.code.punctuation, "\"") + addStyle(AppTheme.code.punctuation, "[") + addStyle(AppTheme.code.punctuation, "]") + addStyle(AppTheme.code.punctuation, "{") + addStyle(AppTheme.code.punctuation, "}") + addStyle(AppTheme.code.punctuation, "(") + addStyle(AppTheme.code.punctuation, ")") + addStyle(AppTheme.code.punctuation, ",") + addStyle(AppTheme.code.keyword, "fun ") + addStyle(AppTheme.code.keyword, "val ") + addStyle(AppTheme.code.keyword, "var ") + addStyle(AppTheme.code.keyword, "private ") + addStyle(AppTheme.code.keyword, "internal ") + addStyle(AppTheme.code.keyword, "for ") + addStyle(AppTheme.code.keyword, "expect ") + addStyle(AppTheme.code.keyword, "actual ") + addStyle(AppTheme.code.keyword, "import ") + addStyle(AppTheme.code.keyword, "package ") + addStyle(AppTheme.code.value, "true") + addStyle(AppTheme.code.value, "false") + addStyle(AppTheme.code.value, Regex("[0-9]*")) + addStyle(AppTheme.code.annotation, Regex("^@[a-zA-Z_]*")) + addStyle(AppTheme.code.comment, Regex("^\\s*//.*")) + } +} + +private fun AnnotatedString.Builder.addStyle(style: SpanStyle, regexp: String) { + addStyle(style, fromLiteral(regexp)) +} + +private fun AnnotatedString.Builder.addStyle(style: SpanStyle, regexp: Regex) { + for (result in regexp.findAll(toString())) { + addStyle(style, result.range.first, result.range.last + 1) + } +} \ No newline at end of file diff --git a/experimental/examples/codeviewer/common/src/jvmMain/kotlin/org/jetbrains/codeviewer/platform/JvmFile.kt b/experimental/examples/codeviewer/shared/src/jvmMain/kotlin/org/jetbrains/codeviewer/platform/JvmFile.kt similarity index 100% rename from experimental/examples/codeviewer/common/src/jvmMain/kotlin/org/jetbrains/codeviewer/platform/JvmFile.kt rename to experimental/examples/codeviewer/shared/src/jvmMain/kotlin/org/jetbrains/codeviewer/platform/JvmFile.kt