Browse Source

Refactor Widgets Gallery sample to use KMM structure and add iOS target (#2491)

Refactor Widgets Gallery sample to use KMM structure and add iOS target
pull/2497/head
Nikita Lipsky 2 years ago committed by GitHub
parent
commit
596e46fdff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      experimental/examples/widgets-gallery/.gitignore
  2. 28
      experimental/examples/widgets-gallery/.run/desktopApp.run.xml
  3. 8
      experimental/examples/widgets-gallery/.run/iosApp.run.xml
  4. 7
      experimental/examples/widgets-gallery/.run/iosApp_.run.xml
  5. 32
      experimental/examples/widgets-gallery/README.md
  6. 33
      experimental/examples/widgets-gallery/androidApp/build.gradle.kts
  7. 24
      experimental/examples/widgets-gallery/androidApp/src/main/AndroidManifest.xml
  8. 15
      experimental/examples/widgets-gallery/androidApp/src/main/kotlin/org/jetbrains/compose/demo/widgets/MainActivity.kt
  9. 170
      experimental/examples/widgets-gallery/androidApp/src/main/res/drawable-v24/ic_launcher_background.xml
  10. 30
      experimental/examples/widgets-gallery/androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml
  11. 5
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  12. 5
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  13. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-hdpi/ic_launcher.png
  14. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png
  15. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-mdpi/ic_launcher.png
  16. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png
  17. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.png
  18. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  19. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png
  20. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  21. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  22. BIN
      experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  23. 16
      experimental/examples/widgets-gallery/androidApp/src/main/res/values-night/themes.xml
  24. 11
      experimental/examples/widgets-gallery/androidApp/src/main/res/values/colors.xml
  25. 3
      experimental/examples/widgets-gallery/androidApp/src/main/res/values/strings.xml
  26. 26
      experimental/examples/widgets-gallery/androidApp/src/main/res/values/themes.xml
  27. 22
      experimental/examples/widgets-gallery/build.gradle.kts
  28. 40
      experimental/examples/widgets-gallery/desktopApp/build.gradle.kts
  29. 13
      experimental/examples/widgets-gallery/desktopApp/src/jvmMain/kotlin/org/jetbrains/compose/demo/widgets/main.kt
  30. 14
      experimental/examples/widgets-gallery/gradle.properties
  31. BIN
      experimental/examples/widgets-gallery/gradle/wrapper/gradle-wrapper.jar
  32. 5
      experimental/examples/widgets-gallery/gradle/wrapper/gradle-wrapper.properties
  33. 240
      experimental/examples/widgets-gallery/gradlew
  34. 91
      experimental/examples/widgets-gallery/gradlew.bat
  35. 1
      experimental/examples/widgets-gallery/iosApp/Configuration/TeamId.xcconfig
  36. 5
      experimental/examples/widgets-gallery/iosApp/Podfile
  37. 380
      experimental/examples/widgets-gallery/iosApp/WidgetsGallery.xcodeproj/project.pbxproj
  38. 48
      experimental/examples/widgets-gallery/iosApp/iosApp/Info.plist
  39. 15
      experimental/examples/widgets-gallery/iosApp/iosApp/iosApp.swift
  40. BIN
      experimental/examples/widgets-gallery/run-configurations.png
  41. 14
      experimental/examples/widgets-gallery/settings.gradle.kts
  42. 72
      experimental/examples/widgets-gallery/shared/build.gradle.kts
  43. 2
      experimental/examples/widgets-gallery/shared/src/androidMain/AndroidManifest.xml
  44. 5
      experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/main.android.kt
  45. 6
      experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt
  46. 18
      experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt
  47. 21
      experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt
  48. 8
      experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt
  49. 13
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/data/DemoDataProvider.kt
  50. 8
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/data/model/Item.kt
  51. 15
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/data/model/Tweet.kt
  52. 6
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt
  53. 20
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Res.kt
  54. 7
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt
  55. 21
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt
  56. 3
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt
  57. 23
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Color.kt
  58. 11
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Shape.kt
  59. 136
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Theme.kt
  60. 43
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Type.kt
  61. 160
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/MainView.kt
  62. 30
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetView.kt
  63. 32
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetsType.kt
  64. 161
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/AppBars.kt
  65. 108
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Buttons.kt
  66. 130
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Chips.kt
  67. 41
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Loaders.kt
  68. 38
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/SnackBars.kt
  69. 86
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/TextInputs.kt
  70. 97
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Texts.kt
  71. 71
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Toggles.kt
  72. 103
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/UICards.kt
  73. 11
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/LayoutModifiers.kt
  74. 91
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/ResizablePanel.kt
  75. 23
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/Text.kt
  76. 96
      experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/VerticalSplittable.kt
  77. BIN
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p1.jpeg
  78. BIN
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p2.jpeg
  79. BIN
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p3.jpeg
  80. BIN
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p6.jpeg
  81. 15
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable/ic_instagram.xml
  82. 9
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable/ic_send.xml
  83. 9
      experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable/ic_twitter.xml
  84. 5
      experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/main.desktop.kt
  85. 12
      experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt
  86. 7
      experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt
  87. 30
      experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt
  88. 5
      experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt
  89. 25
      experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/main.ios.kt
  90. 6
      experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt
  91. 19
      experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt
  92. 21
      experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt
  93. 7
      experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt
  94. 21
      experimental/examples/widgets-gallery/third_party/ComposeCookBook_LICENSE.txt

15
experimental/examples/widgets-gallery/.gitignore vendored

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/
.DS_Store
build/
/captures
.externalNativeBuild
.cxx
iosApp/Podfile.lock
iosApp/Pods/*
iosApp/WidgetsGallery.xcworkspace/*
iosApp/WidgetsGallery.xcodeproj/*
!iosApp/WidgetsGallery.xcodeproj/project.pbxproj
shared/shared.podspec

28
experimental/examples/widgets-gallery/.run/desktopApp.run.xml

@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="desktopApp" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="DEVELOPER_DIR" value="/Applications/Xcode.app/Contents/Developer" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="desktopApp:run" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

8
experimental/examples/widgets-gallery/.run/iosApp.run.xml

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="iosApp" type="AppleRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="WidgetsGallery" TARGET_NAME="WidgetsGallery" CONFIG_NAME="Debug" IS_LOCATION_SIMULATION_SUPPORTED="true" SCHEME_NAME="iosApp" IS_LOCATION_SIMULATION_ALLOWED="true" LOCATION_SCENARIO_ID="com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier" LOCATION_SCENARIO_TYPE="1" APPLICATION_LANGUAGE="IDELaunchSchemeLanguageUseSystemLanguage" APPLICATION_REGION="" RUN_TARGET_PROJECT_NAME="WidgetsGallery" RUN_TARGET_NAME="WidgetsGallery" MAKE_ACTIVE="TRUE" SHOULD_DEBUG_EXTENSIONS="false">
<embedded_app_extension_list />
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

7
experimental/examples/widgets-gallery/.run/iosApp_.run.xml

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="iosApp_" type="KmmRunConfiguration" factoryName="iOS Application" CONFIG_VERSION="1" EXEC_TARGET_ID="9003B6AD-4F7F-48D4-9988-383A8AFC72F5" XCODE_PROJECT="$PROJECT_DIR$/./iosApp/WidgetsGallery.xcworkspace" XCODE_CONFIGURATION="Debug" XCODE_SCHEME="iosApp">
<method v="2">
<option name="com.jetbrains.kmm.ios.BuildIOSAppTask" enabled="true" />
</method>
</configuration>
</component>

32
experimental/examples/widgets-gallery/README.md

@ -0,0 +1,32 @@
# Widgets gallery
This example is derived from
[ComposeCookBook](https://github.com/Gurupreet/ComposeCookBook) project
by Gurupreet Singh ([@Gurupreet](https://github.com/Gurupreet))
published under [MIT license](third_party/ComposeCookBook_LICENSE.txt).
An example of Compose application for Desktop, Android and iOS platforms,
demonstrating how to use various Material widgets.
## How to run
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/WidgetsGallery.xcworkspace` and then
using "Signing & Capabilities" tab of `WidgetsGallery` target.
Then choose **iosApp** configuration in IDE and run it
(may also be referred as `WidgetsGallery` in the Run Configurations or `iosApp_` for Android studio).
## Run on desktop via Gradle
`./gradlew desktopApp:run`
### Building native desktop distribution
```
./gradlew :desktop:packageDistributionForCurrentOS
# outputs are written to desktop/build/compose/binaries
```

33
experimental/examples/widgets-gallery/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.FallingBalls"
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

24
experimental/examples/widgets-gallery/androidApp/src/main/AndroidManifest.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jetbrains.compose.demo.widgets">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity
android:exported="true"
android:name="MainActivity"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

15
experimental/examples/widgets-gallery/androidApp/src/main/kotlin/org/jetbrains/compose/demo/widgets/MainActivity.kt

@ -0,0 +1,15 @@
package org.jetbrains.compose.demo.widgets
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import MainView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainView()
}
}
}

170
experimental/examples/widgets-gallery/androidApp/src/main/res/drawable-v24/ic_launcher_background.xml

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

30
experimental/examples/widgets-gallery/androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

5
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

5
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-hdpi/ic_launcher.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-mdpi/ic_launcher.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
experimental/examples/widgets-gallery/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

16
experimental/examples/widgets-gallery/androidApp/src/main/res/values-night/themes.xml

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- &lt;!&ndash; Base application theme. &ndash;&gt;-->
<!-- <style name="Theme.ComposeCookBook" parent="Theme.MaterialComponents.DayNight.DarkActionBar">-->
<!-- &lt;!&ndash; Primary brand color. &ndash;&gt;-->
<!-- <item name="colorPrimary">@color/green_200</item>-->
<!-- <item name="colorPrimaryVariant">@color/green_700</item>-->
<!-- <item name="colorOnPrimary">@color/black</item>-->
<!-- &lt;!&ndash; Secondary brand color. &ndash;&gt;-->
<!-- <item name="colorSecondary">@color/teal_200</item>-->
<!-- <item name="colorSecondaryVariant">@color/teal_200</item>-->
<!-- <item name="colorOnSecondary">@color/black</item>-->
<!-- &lt;!&ndash; Status bar color. &ndash;&gt;-->
<!-- <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>-->
<!-- &lt;!&ndash; Customize your theme here. &ndash;&gt;-->
<!-- </style>-->
</resources>

11
experimental/examples/widgets-gallery/androidApp/src/main/res/values/colors.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="green_200">#ffa5d6a7</color>
<color name="green_500">#ff4caf50</color>
<color name="green_700">#ff388e3c</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#ff80deea</color>
<color name="purple">#FF833AB4</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

3
experimental/examples/widgets-gallery/androidApp/src/main/res/values/strings.xml

@ -0,0 +1,3 @@
<resources>
<string name="app_name">ComposeWidgets</string>
</resources>

26
experimental/examples/widgets-gallery/androidApp/src/main/res/values/themes.xml

@ -0,0 +1,26 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- &lt;!&ndash; Base application theme. &ndash;&gt;-->
<!-- <style name="Theme.ComposeCookBook" parent="Theme.MaterialComponents.DayNight.DarkActionBar">-->
<!-- &lt;!&ndash; Primary brand color. &ndash;&gt;-->
<!-- <item name="colorPrimary">@color/green_500</item>-->
<!-- <item name="colorPrimaryVariant">@color/green_700</item>-->
<!-- <item name="colorOnPrimary">@color/white</item>-->
<!-- &lt;!&ndash; Secondary brand color. &ndash;&gt;-->
<!-- <item name="colorSecondary">@color/teal_200</item>-->
<!-- <item name="colorSecondaryVariant">@color/teal_700</item>-->
<!-- <item name="colorOnSecondary">@color/black</item>-->
<!-- &lt;!&ndash; Status bar color. &ndash;&gt;-->
<!-- <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>-->
<!-- &lt;!&ndash; Customize your theme here. &ndash;&gt;-->
<!-- <item name="android:windowContentTransitions">true</item>-->
<!-- </style>-->
<!-- <style name="Theme.ComposeCookBook.NoActionBar">-->
<!-- <item name="windowActionBar">false</item>-->
<!-- <item name="windowNoTitle">true</item>-->
<!-- </style>-->
<!-- <style name="Theme.ComposeCookBook.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />-->
<!-- <style name="Theme.ComposeCookBook.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />-->
</resources>

22
experimental/examples/widgets-gallery/build.gradle.kts

@ -0,0 +1,22 @@
buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
mavenLocal()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
classpath("com.android.tools.build:gradle:7.3.1")
classpath("org.jetbrains.compose:compose-gradle-plugin:1.2.1")
}
}
allprojects {
repositories {
google()
mavenCentral()
mavenLocal()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}

40
experimental/examples/widgets-gallery/desktopApp/build.gradle.kts

@ -0,0 +1,40 @@
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
}
kotlin {
jvm {}
sourceSets {
val jvmMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
implementation(project(":shared"))
}
}
}
}
compose.desktop {
application {
mainClass = "org.jetbrains.compose.demo.widgets.MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "ComposeWidgetsGallery"
packageVersion = "1.0.0"
windows {
menu = true
// see https://wixtoolset.org/documentation/manual/v3/howtos/general/generate_guids.html
upgradeUuid = "a61b72be-1b0c-4de5-9607-791c17687428"
}
macOS {
bundleID = "org.jetbrains.compose.demo.widgets"
}
}
}
}

13
experimental/examples/widgets-gallery/desktopApp/src/jvmMain/kotlin/org/jetbrains/compose/demo/widgets/main.kt

@ -0,0 +1,13 @@
package org.jetbrains.compose.demo.widgets
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.singleWindowApplication
import MainView
fun main() = singleWindowApplication(
title = "Widgets Gallery", state = WindowState(size = DpSize(800.dp, 800.dp))
) {
MainView()
}

14
experimental/examples/widgets-gallery/gradle.properties

@ -0,0 +1,14 @@
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

BIN
experimental/examples/widgets-gallery/gradle/wrapper/gradle-wrapper.jar vendored

Binary file not shown.

5
experimental/examples/widgets-gallery/gradle/wrapper/gradle-wrapper.properties vendored

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

240
experimental/examples/widgets-gallery/gradlew vendored

@ -0,0 +1,240 @@
#!/bin/sh
#
# 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.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# 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
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
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
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
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 ;; #(
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
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
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
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
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
# 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" || "$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
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
# 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
fi
# 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.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
experimental/examples/widgets-gallery/gradlew.bat vendored

@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
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"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
: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 %*
:end
@rem End local scope for the variables with windows NT shell
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!
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
:omega

1
experimental/examples/widgets-gallery/iosApp/Configuration/TeamId.xcconfig

@ -0,0 +1 @@
TEAM_ID=

5
experimental/examples/widgets-gallery/iosApp/Podfile

@ -0,0 +1,5 @@
target 'WidgetsGallery' do
use_frameworks!
platform :ios, '14.1'
pod 'shared', :path => '../shared'
end

380
experimental/examples/widgets-gallery/iosApp/WidgetsGallery.xcodeproj/project.pbxproj

@ -0,0 +1,380 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
2152FB042600AC8F00CF470E /* iosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iosApp.swift */; };
C1FC908188C4E8695729CB06 /* Pods_WidgetsGallery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DE96E47030356CE6AD9794A /* Pods_WidgetsGallery.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
1EB65E27D2C0F884D0A1A133 /* Pods-WidgetsGallery.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WidgetsGallery.debug.xcconfig"; path = "Target Support Files/Pods-WidgetsGallery/Pods-WidgetsGallery.debug.xcconfig"; sourceTree = "<group>"; };
2152FB032600AC8F00CF470E /* iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosApp.swift; sourceTree = "<group>"; };
3D7A606AB0AD7636269BD9D0 /* Pods-WidgetsGallery.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WidgetsGallery.release.xcconfig"; path = "Target Support Files/Pods-WidgetsGallery/Pods-WidgetsGallery.release.xcconfig"; sourceTree = "<group>"; };
7555FF7B242A565900829871 /* WidgetsGallery.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WidgetsGallery.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DE96E47030356CE6AD9794A /* Pods_WidgetsGallery.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WidgetsGallery.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AB3632DC29227652001CCB65 /* TeamId.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TeamId.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9964867F0862B4D9FB6ABFC7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C1FC908188C4E8695729CB06 /* Pods_WidgetsGallery.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 = "<group>";
};
7555FF7C242A565900829871 /* Products */ = {
isa = PBXGroup;
children = (
7555FF7B242A565900829871 /* WidgetsGallery.app */,
);
name = Products;
sourceTree = "<group>";
};
7555FF7D242A565900829871 /* iosApp */ = {
isa = PBXGroup;
children = (
7555FF8C242A565B00829871 /* Info.plist */,
2152FB032600AC8F00CF470E /* iosApp.swift */,
);
path = iosApp;
sourceTree = "<group>";
};
AB1DB47929225F7C00F7AF9C /* Configuration */ = {
isa = PBXGroup;
children = (
AB3632DC29227652001CCB65 /* TeamId.xcconfig */,
);
path = Configuration;
sourceTree = "<group>";
};
B62309C7396AD7BF607A63B2 /* Frameworks */ = {
isa = PBXGroup;
children = (
8DE96E47030356CE6AD9794A /* Pods_WidgetsGallery.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
E1DAFBE8E1CFC0878361EF0E /* Pods */ = {
isa = PBXGroup;
children = (
1EB65E27D2C0F884D0A1A133 /* Pods-WidgetsGallery.debug.xcconfig */,
3D7A606AB0AD7636269BD9D0 /* Pods-WidgetsGallery.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
7555FF7A242A565900829871 /* WidgetsGallery */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "WidgetsGallery" */;
buildPhases = (
E8D673591E7196AEA2EA10E2 /* [CP] Check Pods Manifest.lock */,
7555FF77242A565900829871 /* Sources */,
7555FF79242A565900829871 /* Resources */,
9964867F0862B4D9FB6ABFC7 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = WidgetsGallery;
productName = iosApp;
productReference = 7555FF7B242A565900829871 /* WidgetsGallery.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 "WidgetsGallery" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 7555FF72242A565900829871;
productRefGroup = 7555FF7C242A565900829871 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
7555FF7A242A565900829871 /* WidgetsGallery */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
7555FF79242A565900829871 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
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-WidgetsGallery-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-WidgetsGallery.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.WidgetsGallery${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-WidgetsGallery.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.WidgetsGallery${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 "WidgetsGallery" */ = {
isa = XCConfigurationList;
buildConfigurations = (
7555FFA3242A565B00829871 /* Debug */,
7555FFA4242A565B00829871 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "WidgetsGallery" */ = {
isa = XCConfigurationList;
buildConfigurations = (
7555FFA6242A565B00829871 /* Debug */,
7555FFA7242A565B00829871 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 7555FF73242A565900829871 /* Project object */;
}

48
experimental/examples/widgets-gallery/iosApp/iosApp/Info.plist

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>UILaunchScreen</key>
<dict/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

15
experimental/examples/widgets-gallery/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
}
}

BIN
experimental/examples/widgets-gallery/run-configurations.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

14
experimental/examples/widgets-gallery/settings.gradle.kts

@ -0,0 +1,14 @@
pluginManagement {
repositories {
google()
jcenter()
gradlePluginPortal()
mavenCentral()
}
}
rootProject.name = "widgets-gallery"
include(":androidApp")
include(":shared")
include(":desktopApp")

72
experimental/examples/widgets-gallery/shared/build.gradle.kts

@ -0,0 +1,72 @@
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
id("org.jetbrains.compose")
}
version = "1.0-SNAPSHOT"
kotlin {
android()
jvm("desktop")
ios()
iosSimulatorArm64()
cocoapods {
summary = "Shared code for the sample"
homepage = "https://github.com/JetBrains/compose-jb"
ios.deploymentTarget = "14.1"
podfile = project.file("../iosApp/Podfile")
framework {
baseName = "shared"
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.materialIconsExtended)
}
}
val androidMain by getting {
dependencies {
implementation("androidx.appcompat:appcompat:1.5.1")
implementation("androidx.core:core-ktx:1.8.0")
}
}
val iosMain by getting
val iosTest by getting
val iosSimulatorArm64Main by getting {
dependsOn(iosMain)
}
val iosSimulatorArm64Test by getting {
dependsOn(iosTest)
}
val desktopMain by getting {
dependencies {
implementation(compose.desktop.common)
}
}
}
}
android {
compileSdk = 33
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
sourceSets["main"].res.srcDirs("src/androidMain/res", "src/commonMain/resources")
defaultConfig {
minSdk = 24
targetSdk = 33
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

2
experimental/examples/widgets-gallery/shared/src/androidMain/AndroidManifest.xml

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.jetbrains.compose.demo.widgets.platform"/>

5
experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/main.android.kt

@ -0,0 +1,5 @@
import androidx.compose.runtime.Composable
import org.jetbrains.compose.demo.widgets.ui.MainView
@Composable
fun MainView() = MainView()

6
experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt

@ -0,0 +1,6 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
actual fun Modifier.cursorForHorizontalResize() = this

18
experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt

@ -0,0 +1,18 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
@Composable
actual fun painterResource(res: String): Painter {
val id = drawableId(res)
return androidx.compose.ui.res.painterResource(id)
}
// TODO: improve resource loading
private fun drawableId(res: String): Int {
val imageName = res.substringAfterLast("/").substringBeforeLast(".")
val drawableClass = R.drawable::class.java
val field = drawableClass.getDeclaredField(imageName)
return field.get(drawableClass) as Int
}

21
experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt

@ -0,0 +1,21 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
@Composable
actual fun VerticalScrollbar(
modifier: Modifier,
scrollState: ScrollState
) = Unit
@Composable
actual fun VerticalScrollbar(
modifier: Modifier,
scrollState: LazyListState,
itemCount: Int,
averageItemSize: Dp
) = Unit

8
experimental/examples/widgets-gallery/shared/src/androidMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt

@ -0,0 +1,8 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.runtime.Composable
import androidx.compose.foundation.isSystemInDarkTheme as androidSystemIsInDarkTheme
@Composable
actual fun isSystemInDarkTheme(): Boolean =
androidSystemIsInDarkTheme()

13
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/data/DemoDataProvider.kt

@ -0,0 +1,13 @@
package org.jetbrains.compose.demo.widgets.data
import org.jetbrains.compose.demo.widgets.data.model.Item
import org.jetbrains.compose.demo.widgets.data.model.Tweet
import org.jetbrains.compose.demo.widgets.platform.Res
object DemoDataProvider {
val item = Item(
1,
"Awesome List Item",
"Very awesome list item has very awesome subtitle. This is bit long",
)
}

8
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/data/model/Item.kt

@ -0,0 +1,8 @@
package org.jetbrains.compose.demo.widgets.data.model
data class Item(
val id: Int,
val title: String,
val subtitle: String,
val source: String = "demo source"
)

15
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/data/model/Tweet.kt

@ -0,0 +1,15 @@
package org.jetbrains.compose.demo.widgets.data.model
data class Tweet(
val id: Int,
val text: String,
val author: String,
val handle: String,
val time: String,
val authorImageId: String,
val likesCount: Int,
val commentsCount: Int,
val retweetCount: Int,
val source: String,
val tweetImageId: String? = null
)

6
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt

@ -0,0 +1,6 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
expect fun Modifier.cursorForHorizontalResize(): Modifier

20
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Res.kt

@ -0,0 +1,20 @@
package org.jetbrains.compose.demo.widgets.platform
object Res {
object drawable {
val p1 = "drawable-nodpi/p1.jpeg"
val p2 = "drawable-nodpi/p2.jpeg"
val p3 = "drawable-nodpi/p3.jpeg"
val p6 = "drawable-nodpi/p6.jpeg"
val ic_instagram = "drawable/ic_instagram.xml"
val ic_send = "drawable/ic_send.xml"
val ic_twitter = "drawable/ic_twitter.xml"
}
object string {
val spotify_nav_home = "Home"
val spotify_nav_search = "Search"
val spotify_nav_library = "Your Library"
}
}

7
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt

@ -0,0 +1,7 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
@Composable
internal expect fun painterResource(res: String): Painter

21
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt

@ -0,0 +1,21 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
@Composable
internal expect fun VerticalScrollbar(
modifier: Modifier,
scrollState: ScrollState
)
@Composable
internal expect fun VerticalScrollbar(
modifier: Modifier,
scrollState: LazyListState,
itemCount: Int,
averageItemSize: Dp
)

3
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt

@ -0,0 +1,3 @@
package org.jetbrains.compose.demo.widgets.platform
internal expect fun isSystemInDarkTheme(): Boolean

23
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Color.kt

@ -0,0 +1,23 @@
package org.jetbrains.compose.demo.widgets.theme
import androidx.compose.ui.graphics.Color
val green200 = Color(0xffa5d6a7)
val green500 = Color(0xff4caf50)
val green700 = Color(0xff388e3c)
val blue500 = Color(0xFF3F51B5)
val blue200 = Color(0xFF9FA8DA)
val blue700 = Color(0xFF303F9F)
val purple200 = Color(0xFFB39DDB)
val purple = Color(0xFF833AB4)
val purple700 = Color(0xFF512DA8)
val orange200 = Color(0xFFff7961)
val orange500 = Color(0xFFf44336)
val orange700 = Color(0xFFba000d)
val teal200 = Color(0xff80deea)
val twitterColor = Color(0xFF1DA1F2)

11
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Shape.kt

@ -0,0 +1,11 @@
package org.jetbrains.compose.demo.widgets.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes
import androidx.compose.ui.unit.dp
val shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)

136
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Theme.kt

@ -0,0 +1,136 @@
package org.jetbrains.compose.demo.widgets.theme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import org.jetbrains.compose.demo.widgets.platform.isSystemInDarkTheme
import org.jetbrains.compose.demo.widgets.theme.ColorPallet.*
// dark palettes
private val DarkGreenColorPalette = darkColors(
primary = green200,
primaryVariant = green700,
secondary = teal200,
background = Color.Black,
surface = Color.Black,
onPrimary = Color.Black,
onSecondary = Color.White,
onBackground = Color.White,
onSurface = Color.White,
error = Color.Red,
)
private val DarkPurpleColorPalette = darkColors(
primary = purple200,
primaryVariant = purple700,
secondary = teal200,
background = Color.Black,
surface = Color.Black,
onPrimary = Color.Black,
onSecondary = Color.White,
onBackground = Color.White,
onSurface = Color.White,
error = Color.Red,
)
private val DarkBlueColorPalette = darkColors(
primary = blue200,
primaryVariant = blue700,
secondary = teal200,
background = Color.Black,
surface = Color.Black,
onPrimary = Color.Black,
onSecondary = Color.White,
onBackground = Color.White,
onSurface = Color.White,
error = Color.Red,
)
private val DarkOrangeColorPalette = darkColors(
primary = orange200,
primaryVariant = orange700,
secondary = teal200,
background = Color.Black,
surface = Color.Black,
onPrimary = Color.Black,
onSecondary = Color.White,
onBackground = Color.White,
onSurface = Color.White,
error = Color.Red,
)
// Light pallets
private val LightGreenColorPalette = lightColors(
primary = green500,
primaryVariant = green700,
secondary = teal200,
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black
)
private val LightPurpleColorPalette = lightColors(
primary = purple,
primaryVariant = purple700,
secondary = teal200,
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black
)
private val LightBlueColorPalette = lightColors(
primary = blue500,
primaryVariant = blue700,
secondary = teal200,
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black
)
private val LightOrangeColorPalette = lightColors(
primary = orange500,
primaryVariant = orange700,
secondary = teal200,
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black
)
enum class ColorPallet {
PURPLE, GREEN, ORANGE, BLUE
}
@Composable
internal fun WidgetGalleryTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
colorPallet: ColorPallet = GREEN,
content: @Composable() () -> Unit,
) {
val colors = when (colorPallet) {
GREEN -> if (darkTheme) DarkGreenColorPalette else LightGreenColorPalette
PURPLE -> if (darkTheme) DarkPurpleColorPalette else LightPurpleColorPalette
ORANGE -> if (darkTheme) DarkOrangeColorPalette else LightOrangeColorPalette
BLUE -> if (darkTheme) DarkBlueColorPalette else LightBlueColorPalette
}
MaterialTheme(
colors = colors,
typography = typography,
shapes = shapes,
content = content
)
}

43
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/theme/Type.kt

@ -0,0 +1,43 @@
package org.jetbrains.compose.demo.widgets.theme
import androidx.compose.material.Typography
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
val typography = Typography(
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
body2 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
),
button = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.W500,
fontSize = 14.sp
),
caption = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 12.sp,
),
subtitle1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
color = Color.Gray
),
subtitle2 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
color = Color.Gray
),
)

160
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/MainView.kt

@ -0,0 +1,160 @@
package org.jetbrains.compose.demo.widgets.ui
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.SpringSpec
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.hoverable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.jetbrains.compose.demo.widgets.platform.VerticalScrollbar
import org.jetbrains.compose.demo.widgets.theme.WidgetGalleryTheme
import org.jetbrains.compose.demo.widgets.ui.utils.PanelState
import org.jetbrains.compose.demo.widgets.ui.utils.ResizablePanel
import org.jetbrains.compose.demo.widgets.ui.utils.VerticalSplittable
import org.jetbrains.compose.demo.widgets.ui.utils.withoutWidthConstraints
@Composable
internal fun MainView() {
WidgetGalleryTheme {
Surface {
WidgetsPanel()
}
}
}
@Composable
internal fun WidgetsPanel() {
val widgetsTypeState = rememberSaveable { mutableStateOf(WidgetsType.sortedValues.first()) }
val panelState = remember { PanelState() }
val animatedSize = if (panelState.splitter.isResizing) {
if (panelState.isExpanded) panelState.expandedSize else panelState.collapsedSize
} else {
animateDpAsState(
if (panelState.isExpanded) panelState.expandedSize else panelState.collapsedSize,
SpringSpec(stiffness = Spring.StiffnessLow)
).value
}
VerticalSplittable(
Modifier.fillMaxSize(),
panelState.splitter,
onResize = {
panelState.expandedSize =
(panelState.expandedSize + it).coerceAtLeast(panelState.expandedSizeMin)
}
) {
ResizablePanel(
Modifier.width(animatedSize).fillMaxHeight(),
title = "Widgets",
state = panelState
) {
WidgetsListView(widgetsTypeState)
}
Box {
Column {
WidgetsView(
widgetsTypeState,
modifier = Modifier.weight(1f)
)
}
}
}
}
@Composable
private fun WidgetsListView(widgetsTypeState: MutableState<WidgetsType>) {
Box {
with(LocalDensity.current) {
val scrollState = rememberLazyListState()
val fontSize = 14.sp
val lineHeight = fontSize.toDp() * 1.5f
val sortedItems = WidgetsType.sortedValues
LazyColumn(
modifier = Modifier.fillMaxSize().withoutWidthConstraints(),
state = scrollState
) {
items(sortedItems) {
WidgetsListItemViewImpl(it, widgetsTypeState, fontSize, lineHeight)
}
}
VerticalScrollbar(
Modifier.align(Alignment.CenterEnd),
scrollState,
sortedItems.size,
lineHeight
)
}
}
}
@Composable
private fun WidgetsListItemViewImpl(
widgetsType: WidgetsType,
widgetsTypeState: MutableState<WidgetsType>,
fontSize: TextUnit,
height: Dp
) {
val isCurrent = widgetsTypeState.value == widgetsType
Row(
modifier = Modifier
.wrapContentHeight()
.clickable { widgetsTypeState.value = widgetsType }
.semantics {
set(SemanticsProperties.Role, Role.Button)
}
.height(height)
.padding(start = 16.dp)
) {
val inFocusInteractionSource = remember { MutableInteractionSource() }
val inFocus by inFocusInteractionSource.collectIsHoveredAsState()
val textColor = LocalContentColor.current.let {
when {
isCurrent -> it
inFocus -> it.copy(alpha = 0.6f)
else -> it.copy(alpha = 0.4f)
}
}
Text(
text = widgetsType.readableName,
color = textColor,
modifier = Modifier
.align(Alignment.CenterVertically)
.clipToBounds()
.hoverable(inFocusInteractionSource),
softWrap = true,
fontSize = fontSize,
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
}
}

30
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetView.kt

@ -0,0 +1,30 @@
package org.jetbrains.compose.demo.widgets.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import org.jetbrains.compose.demo.widgets.ui.screens.*
@Composable
internal fun WidgetsView(
widgetsTypeState: MutableState<WidgetsType>,
modifier: Modifier
) {
Column(modifier = modifier.verticalScroll(state = rememberScrollState())) {
@Suppress("UNUSED_VARIABLE")
val exhaustive = when (widgetsTypeState.value) {
WidgetsType.APP_BARS -> AppBars()
WidgetsType.BUTTONS -> Buttons()
WidgetsType.CHIPS -> Chips()
WidgetsType.LOADERS -> Loaders()
WidgetsType.SNACK_BARS -> SnackBars()
WidgetsType.TEXT_VIEWS -> TextViews()
WidgetsType.TEXT_INPUTS -> TextInputs()
WidgetsType.TOGGLES -> Toggles()
WidgetsType.UI_CARDS -> UICards()
}
}
}

32
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetsType.kt

@ -0,0 +1,32 @@
package org.jetbrains.compose.demo.widgets.ui
enum class WidgetsType(private val customTitle: String? = null) {
APP_BARS,
BUTTONS,
CHIPS,
LOADERS,
SNACK_BARS,
TEXT_VIEWS,
TEXT_INPUTS,
TOGGLES,
UI_CARDS("UI Cards");
val readableName: String by lazy {
name.split("_")
.map { it.lowercase() }
.mapIndexed { i, it ->
if (i == 0) it.replaceFirstChar {
if (it.isLowerCase()) it.titlecase() else it.toString()
} else it
}.joinToString(" ")
}
val title: String
get() = customTitle ?: readableName
companion object {
val sortedValues: List<WidgetsType> by lazy {
values().sortedBy { it.name }
}
}
}

161
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/AppBars.kt

@ -0,0 +1,161 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.MoreHoriz
import androidx.compose.material.icons.filled.StarBorder
import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.platform.Res
import org.jetbrains.compose.demo.widgets.platform.painterResource
import org.jetbrains.compose.demo.widgets.theme.twitterColor
import org.jetbrains.compose.demo.widgets.ui.utils.SubtitleText
import org.jetbrains.compose.demo.widgets.ui.utils.TitleText
@Composable
internal fun AppBars() {
TopAppBarsDemo()
BottomAppBarDemo()
NavigationBarDemo()
}
@Composable
private fun TopAppBarsDemo() {
SubtitleText(subtitle = "Top App bar")
TopAppBar(
title = { Text(text = "Home") },
elevation = 8.dp,
navigationIcon = {
IconButton(onClick = {}) {
Icon(Icons.Default.ArrowBack, contentDescription = "ArrowBack")
}
}
)
Spacer(modifier = Modifier.height(8.dp))
TopAppBar(
title = { Text(text = "Instagram") },
backgroundColor = MaterialTheme.colors.surface,
contentColor = MaterialTheme.colors.onSurface,
elevation = 8.dp,
navigationIcon = {
IconButton(onClick = {}) {
Icon(painterResource(Res.drawable.ic_instagram), contentDescription = "Instagram")
}
},
actions = {
IconButton(onClick = {}) {
Icon(painterResource(Res.drawable.ic_send), contentDescription = "Send")
}
}
)
Spacer(modifier = Modifier.height(8.dp))
TopAppBar(
title = {
Icon(
painterResource(Res.drawable.ic_twitter),
contentDescription = "Twitter",
tint = twitterColor,
modifier = Modifier.fillMaxWidth()
)
},
backgroundColor = MaterialTheme.colors.surface,
contentColor = MaterialTheme.colors.onSurface,
elevation = 8.dp,
navigationIcon = {
Image(
painterResource(Res.drawable.p6),
contentDescription = "",
modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
.requiredSize(32.dp).clip(CircleShape)
)
},
actions = {
Icon(
Icons.Default.StarBorder,
contentDescription = "",
modifier = Modifier.padding(horizontal = 8.dp)
)
}
)
Spacer(modifier = Modifier.height(8.dp))
}
@Composable
private fun BottomAppBarDemo() {
Spacer(modifier = Modifier.height(16.dp))
SubtitleText("Bottom app bars: Note bottom app bar support FAB cutouts when used with scafolds see demoUI crypto app")
BottomAppBar(
cutoutShape = CircleShape
) {
IconButton(onClick = {}) {
Icon(Icons.Default.MoreHoriz, contentDescription = "")
}
TitleText(title = "Bottom App Bar")
}
}
@Composable
private fun NavigationBarDemo() {
Spacer(modifier = Modifier.height(16.dp))
SubtitleText(subtitle = "Bottom Navigation Bars")
val navItemState = remember { mutableStateOf(NavType.HOME) }
BottomNavigation(backgroundColor = MaterialTheme.colors.surface) {
BottomNavigationItem(
icon = { Icon(Icons.Outlined.Home, contentDescription = "Home") },
selected = navItemState.value == NavType.HOME,
onClick = { navItemState.value = NavType.HOME },
label = { Text(text = Res.string.spotify_nav_home) },
)
BottomNavigationItem(
icon = { Icon(Icons.Outlined.Search, contentDescription = "Search") },
selected = navItemState.value == NavType.SEARCH,
onClick = { navItemState.value = NavType.SEARCH },
label = { Text(text = Res.string.spotify_nav_search) }
)
BottomNavigationItem(
icon = { Icon(Icons.Outlined.LibraryMusic, contentDescription = "LibraryMusic") },
selected = navItemState.value == NavType.LIBRARY,
onClick = { navItemState.value = NavType.LIBRARY },
label = { Text(text = Res.string.spotify_nav_library) }
)
}
Spacer(modifier = Modifier.height(16.dp))
BottomNavigation {
BottomNavigationItem(
icon = { Icon(Icons.Outlined.ReadMore, contentDescription = "ReadMore") },
selected = navItemState.value == NavType.HOME,
onClick = { navItemState.value = NavType.HOME },
)
BottomNavigationItem(
icon = { Icon(Icons.Outlined.Search, contentDescription = "Search") },
selected = navItemState.value == NavType.SEARCH,
onClick = { navItemState.value = NavType.SEARCH },
)
BottomNavigationItem(
icon = { Icon(Icons.Outlined.CleanHands, contentDescription = "CleanHands") },
selected = navItemState.value == NavType.LIBRARY,
onClick = { navItemState.value = NavType.LIBRARY },
)
}
}
private enum class NavType {
HOME, SEARCH, LIBRARY
}

108
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Buttons.kt

@ -0,0 +1,108 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.theme.purple
import org.jetbrains.compose.demo.widgets.theme.purple200
import org.jetbrains.compose.demo.widgets.theme.typography
@Composable
internal fun Buttons() {
Column {
Button(onClick = {}, modifier = Modifier.padding(8.dp)) {
Text(text = "Main Button")
}
TextButton(onClick = {}, modifier = Modifier.padding(8.dp)) {
Text(text = "Text Button")
}
TextButton(onClick = {}, modifier = Modifier.padding(8.dp), enabled = false) {
Text(text = "Text Disabled")
}
Button(onClick = {}, modifier = Modifier.padding(8.dp), enabled = false) {
Text(text = "Disabled")
}
Button(
onClick = {},
modifier = Modifier.padding(8.dp),
elevation = ButtonDefaults.elevation()
) {
Text(text = "Flat")
}
Button(
onClick = {},
modifier = Modifier.padding(8.dp),
shape = RoundedCornerShape(12.dp)
) {
Text(text = "Rounded")
}
OutlinedButton(onClick = {}, modifier = Modifier.padding(8.dp)) {
Text(text = "Outline")
}
Button(onClick = {}, modifier = Modifier.padding(8.dp)) {
Row {
Icon(Icons.Default.FavoriteBorder, contentDescription = null, modifier = Modifier.padding(end = 4.dp))
Text(text = "Icon Button")
}
}
Button(onClick = {}, modifier = Modifier.padding(8.dp)) {
Text(text = "Icon Button")
Icon(Icons.Default.FavoriteBorder, contentDescription = null, modifier = Modifier.padding(start = 4.dp))
}
//custom background buttons
val outlineButtonColor = ButtonDefaults.outlinedButtonColors(
contentColor = purple200,
)
val mainButtonColor = ButtonDefaults.buttonColors(
backgroundColor = purple,
contentColor = MaterialTheme.colors.surface
)
OutlinedButton(
colors = outlineButtonColor,
onClick = {},
modifier = Modifier.padding(8.dp)
) {
Text(text = "Outline colors")
}
Button(colors = mainButtonColor, onClick = {}, modifier = Modifier.padding(8.dp)) {
Text(text = "Custom colors")
}
val horizontalGradient = Brush.horizontalGradient(
colors = listOf(MaterialTheme.colors.primary, MaterialTheme.colors.primaryVariant),
0f,
250f
)
val verticalGradient = Brush.verticalGradient(
colors = listOf(MaterialTheme.colors.primary, MaterialTheme.colors.primaryVariant),
startY = 0f,
endY = 100f
)
Text(
text = "Horizontal gradient",
style = typography.body2.copy(color = Color.White),
modifier = Modifier.padding(12.dp).clickable(onClick = {})
.clip(RoundedCornerShape(4.dp))
.background(brush = horizontalGradient).padding(12.dp)
)
Text(
text = "Vertical gradient",
style = typography.body1.copy(color = Color.White),
modifier = Modifier.padding(12.dp).clickable(onClick = {})
.clip(RoundedCornerShape(4.dp))
.background(brush = verticalGradient).padding(12.dp)
)
}
}

130
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Chips.kt

@ -0,0 +1,130 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.platform.Res
import org.jetbrains.compose.demo.widgets.platform.painterResource
import org.jetbrains.compose.demo.widgets.ui.utils.SubtitleText
@Composable
internal fun Chips() {
// There is no in-built chips but you can make yours like below
SubtitleText(subtitle = "Custom chips with surface")
Column(modifier = Modifier.padding(8.dp)) {
YoutubeChip(selected = true, text = "Chip", modifier = Modifier.padding(horizontal = 8.dp))
Spacer(modifier = Modifier.padding(8.dp))
YoutubeChip(
selected = false,
text = "Inactive",
modifier = Modifier.padding(horizontal = 8.dp)
)
Spacer(modifier = Modifier.padding(8.dp))
CustomImageChip(text = "custom", imageId = Res.drawable.p2, selected = true)
Spacer(modifier = Modifier.padding(8.dp))
CustomImageChip(text = "custom2", imageId = Res.drawable.p6, selected = false)
}
SubtitleText(subtitle = "Buttons with circle clipping.")
Column(modifier = Modifier.padding(8.dp)) {
Button(
onClick = {},
modifier = Modifier.padding(8.dp).clip(CircleShape)
) {
Text(text = "Chip button")
}
Button(
onClick = {},
enabled = false,
modifier = Modifier.padding(8.dp).clip(CircleShape)
) {
Text(text = "Disabled chip")
}
}
}
//Inspired from jetcaster sample. I hope compose can add simple Chip UI element that can
// support images or icons with multiple states.
@Composable
private fun CustomImageChip(
text: String,
imageId: String,
selected: Boolean,
modifier: Modifier = Modifier
) {
Surface(
color = when {
selected -> MaterialTheme.colors.primary
else -> Color.Transparent
},
contentColor = when {
selected -> MaterialTheme.colors.onPrimary
else -> Color.LightGray
},
shape = RoundedCornerShape(16.dp),
border = BorderStroke(
width = 1.dp,
color = when {
selected -> MaterialTheme.colors.primary
else -> Color.LightGray
}
),
modifier = modifier
) {
Row(modifier = Modifier) {
Image(
painterResource(imageId),
contentDescription = null,
modifier = Modifier.padding(8.dp).requiredSize(20.dp).clip(CircleShape)
)
Text(
text = text,
style = MaterialTheme.typography.body2,
modifier = Modifier.padding(end = 8.dp, top = 8.dp, bottom = 8.dp)
)
}
}
}
@Composable
private fun YoutubeChip(selected: Boolean, text: String, modifier: Modifier = Modifier) {
Surface(
color = when {
selected -> MaterialTheme.colors.onSurface
else -> Color.Transparent
},
contentColor = when {
selected -> MaterialTheme.colors.onPrimary
else -> Color.LightGray
},
shape = CircleShape,
border = BorderStroke(
width = 1.dp,
color = when {
selected -> MaterialTheme.colors.primary
else -> Color.LightGray
}
),
modifier = modifier
) {
Text(
text = text,
textAlign = TextAlign.Center,
style = MaterialTheme.typography.body2,
modifier = Modifier.padding(8.dp)
)
}
}

41
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Loaders.kt

@ -0,0 +1,41 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
internal fun Loaders() {
AlignedColumn {
CircularProgressIndicator()
}
AlignedColumn {
CircularProgressIndicator(strokeWidth = 8.dp)
}
AlignedColumn {
LinearProgressIndicator()
}
AlignedColumn {
LinearProgressIndicator()
Text(text = "Loading with text...", modifier = Modifier.padding(8.dp))
}
}
@Composable
private fun AlignedColumn(content: @Composable () -> Unit) {
Column(
modifier = Modifier.fillMaxWidth().padding(16.dp)
) {
content()
}
}

38
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/SnackBars.kt

@ -0,0 +1,38 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Snackbar
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.theme.typography
@Composable
internal fun SnackBars() {
Snackbar(modifier = Modifier.padding(4.dp)) {
Text(text = "This is a basic snackbar")
}
Snackbar(
modifier = Modifier.padding(4.dp),
action = {
TextButton(onClick = {}) {
Text(text = "Remove")
}
}
) {
Text(text = "This is a basic Snackbar with action item")
}
Snackbar(
modifier = Modifier.padding(4.dp),
actionOnNewLine = true,
action = {
TextButton(onClick = {}) {
Text(text = "Remove")
}
}
) {
Text(text = "Snackbar with action item below text")
}
}

86
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/TextInputs.kt

@ -0,0 +1,86 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Icon
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Email
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
@Composable
internal fun TextInputs() {
var text by remember { mutableStateOf(TextFieldValue("")) }
// TODO Explore CoreTextField
// CoreTextField(
// value = text,
// onValueChange = { newValue -> text = newValue },
// modifier = Modifier.padding(8.dp).preferredSize(0.dp),
// cursorColor = Color.Magenta
// )
TextField(
value = text,
onValueChange = { newValue -> text = newValue },
modifier = Modifier.padding(8.dp).fillMaxWidth(),
label = { Text("label") },
placeholder = { Text("placeholder") }
)
OutlinedTextField(
value = text,
modifier = Modifier.padding(8.dp).fillMaxWidth(),
label = { Text(text = "Password") },
placeholder = { Text(text = "12334444") },
visualTransformation = PasswordVisualTransformation(),
onValueChange = {
text = it
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
)
OutlinedTextField(
value = text,
leadingIcon = { Icon(Icons.Default.Email, contentDescription = "Email") },
modifier = Modifier.padding(8.dp).fillMaxWidth(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
label = { Text(text = "Email address") },
placeholder = { Text(text = "Your email") },
onValueChange = {
text = it
}
)
OutlinedTextField(
value = text,
leadingIcon = { Icon(Icons.Default.Email, contentDescription = "Email") },
trailingIcon = { Icon(Icons.Default.Edit, contentDescription = "Edit") },
modifier = Modifier.padding(8.dp).fillMaxWidth(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
label = { Text(text = "Email address") },
placeholder = { Text(text = "Your email") },
onValueChange = {
text = it
}
)
var numberText by remember { mutableStateOf(TextFieldValue("")) }
OutlinedTextField(value = numberText,
modifier = Modifier.padding(8.dp).fillMaxWidth(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
label = { Text(text = "Phone number") },
placeholder = { Text(text = "88888888") },
onValueChange = {
numberText = it
}
)
}

97
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Texts.kt

@ -0,0 +1,97 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.theme.typography
import org.jetbrains.compose.demo.widgets.ui.utils.SubtitleText
@Composable
internal fun TextViews() {
Column {
val textModifier = Modifier.padding(horizontal = 8.dp)
SubtitleText(subtitle = "Font weights")
Text(text = "Plain", modifier = textModifier)
Text(
text = "Medium Bold",
style = typography.body1.copy(fontWeight = FontWeight.Medium),
modifier = textModifier
)
Text(
text = "Bold",
style = typography.body1.copy(fontWeight = FontWeight.Bold),
modifier = textModifier
)
Text(
text = "Extra Bold",
style = typography.body1.copy(fontWeight = FontWeight.Bold),
modifier = textModifier
)
SubtitleText(subtitle = "Text decorations")
Text(text = "Default", modifier = textModifier)
Text(
text = "Underline",
textDecoration = TextDecoration.Underline,
modifier = textModifier
)
Text(
text = "LineThrough",
textDecoration = TextDecoration.LineThrough,
modifier = textModifier
)
Text(
text = "UnderlineLineThrough",
textDecoration = TextDecoration.combine(
listOf(
TextDecoration.Underline,
TextDecoration.LineThrough
)
),
modifier = textModifier
)
SubtitleText(subtitle = "Overflow")
Text(
text = "Ellipsis: This text is supposed to ellipsis with max 1 line allowed for this",
overflow = TextOverflow.Ellipsis,
modifier = textModifier,
maxLines = 1
)
Text(
text = "Clip: This text is supposed to clip with max 1 line allowed for this",
overflow = TextOverflow.Clip,
modifier = textModifier,
maxLines = 1
)
}
/* TODO: https://github.com/JetBrains/compose-jb/issues/106
SubtitleText(subtitle = "font family dynamic")
Row {
Text(text = "Default", modifier = textModifier)
Text(
text = "Cursive",
style = typography.body1.copy(fontFamily = FontFamily.Cursive),
modifier = textModifier
)
Text(
text = "SansSerif",
style = typography.body1.copy(fontFamily = FontFamily.SansSerif),
modifier = textModifier
)
Text(
text = "Monospace",
style = typography.body1.copy(fontFamily = FontFamily.Monospace),
modifier = textModifier
)
} */
}

71
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Toggles.kt

@ -0,0 +1,71 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
internal fun Toggles() {
Column {
var checked by remember { mutableStateOf(true) }
Checkbox(
checked = checked,
modifier = Modifier.padding(8.dp),
onCheckedChange = { checked = !checked }
)
var switched by remember { mutableStateOf(true) }
Switch(
checked = switched,
colors = SwitchDefaults.colors(checkedThumbColor = MaterialTheme.colors.primary),
modifier = Modifier.padding(8.dp),
onCheckedChange = { switched = it }
)
AlignedColumn {
var selected by remember { mutableStateOf("Kotlin") }
for (lang in arrayOf("Kotlin", "Java", "Swift")) {
Row(verticalAlignment = Alignment.CenterVertically) {
RadioButton(selected = selected == lang, onClick = { selected = lang })
Text(
text = lang,
modifier = Modifier.clickable(onClick = { selected = lang }).padding(start = 4.dp)
)
}
}
}
var sliderState by remember { mutableStateOf(0f) }
Slider(value = sliderState, modifier = Modifier.fillMaxWidth().padding(8.dp),
onValueChange = { newValue ->
sliderState = newValue
}
)
var sliderState2 by remember { mutableStateOf(20f) }
Slider(value = sliderState2, modifier = Modifier.fillMaxWidth().padding(8.dp),
valueRange = 0f..100f,
steps = 5,
colors = SliderDefaults.colors(thumbColor = MaterialTheme.colors.secondary),
onValueChange = { newValue ->
sliderState2 = newValue
}
)
}
}
@Composable
private fun AlignedColumn(content: @Composable () -> Unit) {
Column(
modifier = Modifier.fillMaxWidth().padding(16.dp)
) {
content()
}
}

103
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/UICards.kt

@ -0,0 +1,103 @@
package org.jetbrains.compose.demo.widgets.ui.screens
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ShoppingCart
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.data.DemoDataProvider
import org.jetbrains.compose.demo.widgets.platform.Res
import org.jetbrains.compose.demo.widgets.platform.painterResource
import org.jetbrains.compose.demo.widgets.theme.typography
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun UICards() {
val item = remember { DemoDataProvider.item }
Text(
text = "Inbuilt box as container for any Clipping/Alignment controls",
style = typography.subtitle1,
modifier = Modifier.padding(8.dp)
)
Card(
modifier = Modifier.padding(8.dp).fillMaxWidth(),
backgroundColor = MaterialTheme.colors.primary,
shape = RoundedCornerShape(topStart = 16.dp, bottomEnd = 16.dp)
) {
Column {
Text(
text = item.title,
modifier = Modifier.padding(8.dp),
color = MaterialTheme.colors.onPrimary
)
Text(
text = item.subtitle,
modifier = Modifier.padding(8.dp),
color = MaterialTheme.colors.onPrimary
)
}
}
Divider()
Text(text = "Inbuilt Card", style = typography.subtitle1, modifier = Modifier.padding(8.dp))
Card(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
shape = RoundedCornerShape(4.dp),
elevation = 4.dp
) {
Row {
Image(
painterResource(Res.drawable.p3),
contentDescription = null,
modifier = Modifier.requiredSize(60.dp)
)
Text(text = item.title, modifier = Modifier.padding(16.dp))
}
}
Divider()
Text(
text = "In-built ListItems",
style = typography.subtitle1,
modifier = Modifier.padding(8.dp)
)
ListItem(text = { Text(item.title) }, secondaryText = { Text(item.subtitle) })
Divider(modifier = Modifier.padding(4.dp))
ListItem(
text = { Text(item.title) },
secondaryText = { Text(item.subtitle) },
singleLineSecondaryText = false
)
Divider(modifier = Modifier.padding(4.dp))
ListItem(text = { Text(item.title) }, secondaryText = { Text(item.subtitle) }, icon = {
Image(
painterResource(Res.drawable.p3),
contentDescription = null
)
})
Divider(modifier = Modifier.padding(4.dp))
//I am not sure why this is not going multiline for secondaryText...
ListItem(
text = { Text(item.title) },
secondaryText = { Text(item.subtitle) },
icon = { Image(painterResource(Res.drawable.p1), contentDescription = null) },
overlineText = { Text("Overline text") },
singleLineSecondaryText = false
)
Divider()
ListItem(
text = { Text(item.title) },
secondaryText = { Text(item.subtitle) },
icon = { Image(painterResource(Res.drawable.p2), contentDescription = null) },
trailing = { Icon(Icons.Default.ShoppingCart, contentDescription = null) },
singleLineSecondaryText = false
)
Divider()
}

11
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/LayoutModifiers.kt

@ -0,0 +1,11 @@
package org.jetbrains.compose.demo.widgets.ui.utils
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.layout
fun Modifier.withoutWidthConstraints() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints.copy(maxWidth = Int.MAX_VALUE))
layout(constraints.maxWidth, placeable.height) {
placeable.place(0, 0)
}
}

91
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/ResizablePanel.kt

@ -0,0 +1,91 @@
package org.jetbrains.compose.demo.widgets.ui.utils
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class PanelState {
val collapsedSize = 40.dp
var expandedSize by mutableStateOf(110.dp)
val expandedSizeMin = 120.dp
var isExpanded by mutableStateOf(true)
val splitter = SplitterState()
}
@Composable
internal fun ResizablePanel(
modifier: Modifier,
state: PanelState,
title: String,
content: @Composable () -> Unit,
) {
val alpha = animateFloatAsState(
if (state.isExpanded) 1f else 0f,
SpringSpec(stiffness = Spring.StiffnessLow),
).value
Box(modifier) {
Column {
Row(Modifier
.height(32.dp)
.padding(6.dp)
.semantics(mergeDescendants = false) {
val text = if (state.isExpanded) "Collapse" else "Expand"
set(SemanticsProperties.Text, listOf(
AnnotatedString("$text $title panel")
))
set(SemanticsProperties.Role, Role.Button)
}
.clickable { state.isExpanded = !state.isExpanded }
) {
Icon(
if (state.isExpanded) Icons.Default.ArrowBack else Icons.Default.ArrowForward,
contentDescription = if (state.isExpanded) "Collapse" else "Expand",
tint = LocalContentColor.current,
modifier = Modifier
.size(24.dp)
.padding(start = 2.dp, end = 2.dp, bottom = 2.dp)
)
Text(
text = if (state.isExpanded) title else "",
modifier = Modifier.fillMaxWidth().clipToBounds(),
fontSize = 14.sp
)
}
if (state.isExpanded) {
Box(
Modifier
.fillMaxWidth()
.height(1.dp)
.background(Color.Gray)
)
Column(Modifier.fillMaxSize().padding(top = 4.dp).graphicsLayer(alpha = alpha)) {
content()
}
}
}
}
}

23
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/Text.kt

@ -0,0 +1,23 @@
package org.jetbrains.compose.demo.widgets.ui.utils
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.jetbrains.compose.demo.widgets.theme.typography
@Composable
internal fun SubtitleText(subtitle: String, modifier: Modifier = Modifier) {
Text(text = subtitle, style = typography.subtitle2, modifier = modifier.padding(8.dp))
}
@Composable
internal fun TitleText(title: String) {
Text(
text = title,
style = typography.h6.copy(fontSize = 14.sp),
modifier = Modifier.padding(8.dp)
)
}

96
experimental/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/VerticalSplittable.kt

@ -0,0 +1,96 @@
package org.jetbrains.compose.demo.widgets.ui.utils
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.demo.widgets.platform.cursorForHorizontalResize
class SplitterState {
var isResizing by mutableStateOf(false)
var isResizeEnabled by mutableStateOf(true)
}
@Composable
internal fun VerticalSplittable(
modifier: Modifier,
splitterState: SplitterState,
onResize: (delta: Dp) -> Unit,
children: @Composable () -> Unit
) = Layout({
children()
VerticalSplitter(splitterState, onResize)
}, modifier, measurePolicy = { measurables, constraints ->
require(measurables.size == 3)
val firstPlaceable = measurables[0].measure(constraints.copy(minWidth = 0))
val secondWidth = constraints.maxWidth - firstPlaceable.width
val secondPlaceable = measurables[1].measure(
Constraints(
minWidth = secondWidth,
maxWidth = secondWidth,
minHeight = constraints.maxHeight,
maxHeight = constraints.maxHeight
)
)
val splitterPlaceable = measurables[2].measure(constraints)
layout(constraints.maxWidth, constraints.maxHeight) {
firstPlaceable.place(0, 0)
secondPlaceable.place(firstPlaceable.width, 0)
splitterPlaceable.place(firstPlaceable.width, 0)
}
})
@Composable
internal fun VerticalSplitter(
splitterState: SplitterState,
onResize: (delta: Dp) -> Unit,
color: Color = Color.DarkGray
) = Box {
val density = LocalDensity.current
Box(
Modifier
.width(8.dp)
.fillMaxHeight()
.run {
if (splitterState.isResizeEnabled) {
this.draggable(
state = rememberDraggableState {
with(density) {
onResize(it.toDp())
}
},
orientation = Orientation.Horizontal,
startDragImmediately = true,
onDragStarted = { splitterState.isResizing = true },
onDragStopped = { splitterState.isResizing = false }
).cursorForHorizontalResize()
} else {
this
}
}
)
Box(
Modifier
.width(1.dp)
.fillMaxHeight()
.background(color)
)
}

BIN
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p1.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p2.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p3.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable-nodpi/p6.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

15
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable/ic_instagram.xml

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF000000"
android:pathData="M352,0H160C71.648,0 0,71.648 0,160v192c0,88.352 71.648,160 160,160h192c88.352,0 160,-71.648 160,-160V160C512,71.648 440.352,0 352,0zM464,352c0,61.76 -50.24,112 -112,112H160c-61.76,0 -112,-50.24 -112,-112V160C48,98.24 98.24,48 160,48h192c61.76,0 112,50.24 112,112V352z" />
<path
android:fillColor="#FF000000"
android:pathData="M256,128c-70.688,0 -128,57.312 -128,128s57.312,128 128,128s128,-57.312 128,-128S326.688,128 256,128zM256,336c-44.096,0 -80,-35.904 -80,-80c0,-44.128 35.904,-80 80,-80s80,35.872 80,80C336,300.096 300.096,336 256,336z" />
<path
android:fillColor="#FF000000"
android:pathData="M393.6,118.4m-17.056,0a17.056,17.056 0,1 1,34.112 0a17.056,17.056 0,1 1,-34.112 0" />
</vector>

9
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable/ic_send.xml

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="512.001"
android:viewportHeight="512.001">
<path
android:fillColor="#FF000000"
android:pathData="M507.608,4.395c-4.243,-4.244 -10.609,-5.549 -16.177,-3.321L9.43,193.872c-5.515,2.206 -9.208,7.458 -9.42,13.395c-0.211,5.936 3.101,11.437 8.445,14.029l190.068,92.181l92.182,190.068c2.514,5.184 7.764,8.455 13.493,8.455c0.178,0 0.357,-0.003 0.536,-0.01c5.935,-0.211 11.189,-3.904 13.394,-9.419l192.8,-481.998C513.156,15.001 511.851,8.638 507.608,4.395zM52.094,209.118L434.72,56.069L206.691,284.096L52.094,209.118zM302.883,459.907l-74.979,-154.599l228.03,-228.027L302.883,459.907z" />
</vector>

9
experimental/examples/widgets-gallery/shared/src/commonMain/resources/drawable/ic_twitter.xml

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#000000"
android:pathData="M459.37,151.716c0.325,4.548 0.325,9.097 0.325,13.645 0,138.72 -105.583,298.558 -298.558,298.558 -59.452,0 -114.68,-17.219 -161.137,-47.106 8.447,0.974 16.568,1.299 25.34,1.299 49.055,0 94.213,-16.568 130.274,-44.832 -46.132,-0.975 -84.792,-31.188 -98.112,-72.772 6.498,0.974 12.995,1.624 19.818,1.624 9.421,0 18.843,-1.3 27.614,-3.573 -48.081,-9.747 -84.143,-51.98 -84.143,-102.985v-1.299c13.969,7.797 30.214,12.67 47.431,13.319 -28.264,-18.843 -46.781,-51.005 -46.781,-87.391 0,-19.492 5.197,-37.36 14.294,-52.954 51.655,63.675 129.3,105.258 216.365,109.807 -1.624,-7.797 -2.599,-15.918 -2.599,-24.04 0,-57.828 46.782,-104.934 104.934,-104.934 30.213,0 57.502,12.67 76.67,33.137 23.715,-4.548 46.456,-13.32 66.599,-25.34 -7.798,24.366 -24.366,44.833 -46.132,57.827 21.117,-2.273 41.584,-8.122 60.426,-16.243 -14.292,20.791 -32.161,39.308 -52.628,54.253z" />
</vector>

5
experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/main.desktop.kt

@ -0,0 +1,5 @@
import androidx.compose.runtime.Composable
import org.jetbrains.compose.demo.widgets.ui.MainView
@Composable
fun MainView() = MainView()

12
experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt

@ -0,0 +1,12 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.input.pointer.pointerMoveFilter
import java.awt.Cursor
actual fun Modifier.cursorForHorizontalResize(): Modifier =
this.pointerHoverIcon(PointerIcon(Cursor(Cursor.E_RESIZE_CURSOR)))

7
experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt

@ -0,0 +1,7 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
@Composable
actual fun painterResource(res: String): Painter = androidx.compose.ui.res.painterResource(res)

30
experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt

@ -0,0 +1,30 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
@Composable
actual fun VerticalScrollbar(
modifier: Modifier,
scrollState: ScrollState
) = androidx.compose.foundation.VerticalScrollbar(
rememberScrollbarAdapter(scrollState),
modifier
)
@OptIn(ExperimentalFoundationApi::class)
@Composable
actual fun VerticalScrollbar(
modifier: Modifier,
scrollState: LazyListState,
itemCount: Int,
averageItemSize: Dp
) = androidx.compose.foundation.VerticalScrollbar(
rememberScrollbarAdapter(scrollState),
modifier
)

5
experimental/examples/widgets-gallery/shared/src/desktopMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt

@ -0,0 +1,5 @@
package org.jetbrains.compose.demo.widgets.platform
import org.jetbrains.skiko.SystemTheme
actual fun isSystemInDarkTheme(): Boolean = org.jetbrains.skiko.currentSystemTheme == SystemTheme.DARK

25
experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/main.ios.kt

@ -0,0 +1,25 @@
/*
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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
fun MainViewController() : UIViewController =
Application("Widgets Gallery") {
Column {
// To skip upper part of screen.
Box(
modifier = Modifier
.height(30.dp)
)
MainView()
}
}

6
experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Mouse.kt

@ -0,0 +1,6 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
actual fun Modifier.cursorForHorizontalResize() = this

19
experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Resources.kt

@ -0,0 +1,19 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.runtime.Composable
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.painter.Painter
@Composable
internal actual fun painterResource(res: String): Painter =
// TODO: use resource API
object : Painter() {
override val intrinsicSize: Size
get() = Size(16f, 16f)
override fun DrawScope.onDraw() {
drawRect(color = Color.Red)
}
}

21
experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Scrollbar.kt

@ -0,0 +1,21 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
@Composable
internal actual fun VerticalScrollbar(
modifier: Modifier,
scrollState: ScrollState
) = Unit
@Composable
internal actual fun VerticalScrollbar(
modifier: Modifier,
scrollState: LazyListState,
itemCount: Int,
averageItemSize: Dp
) = Unit

7
experimental/examples/widgets-gallery/shared/src/iosMain/kotlin/org/jetbrains/compose/demo/widgets/platform/System.kt

@ -0,0 +1,7 @@
package org.jetbrains.compose.demo.widgets.platform
import androidx.compose.runtime.Composable
import org.jetbrains.skiko.SystemTheme
@Composable
internal actual fun isSystemInDarkTheme(): Boolean = org.jetbrains.skiko.currentSystemTheme == SystemTheme.DARK

21
experimental/examples/widgets-gallery/third_party/ComposeCookBook_LICENSE.txt vendored

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Gurupreet Singh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading…
Cancel
Save