Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for IJP 24.1 #290

Merged
merged 12 commits into from
Jan 31, 2024
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
supported-ij-version:
- 232
- 233
- 241

steps:
- uses: actions/checkout@v3
Expand All @@ -36,6 +37,7 @@ jobs:
supported-ij-version:
- 232
- 233
- 241

steps:
- uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/check-ide-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
supported-ij-version:
- 232
- 233
- 241

steps:
- uses: actions/checkout@v3
Expand Down
113 changes: 110 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[![JetBrains incubator](https://img.shields.io/badge/JetBrains-incubator-yellow?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIuMDAwMDEiIHZpZXdCb3g9IjAgMCAzMiAzMi4wMDAwMSIgd2lkdGg9IjMyIj48c2NyaXB0IHhtbG5zPSIiLz48cGF0aCBkPSJtMCAwaDMydjMyLjAwMDAxaC0zMnoiLz48cGF0aCBkPSJtNCAyNi4wMDAwMWgxMnYyaC0xMnoiIGZpbGw9IiNmZmYiLz48L3N2Zz4=)](https://github.com/JetBrains#jetbrains-on-github) [![CI checks](https://img.shields.io/github/actions/workflow/status/JetBrains/jewel/build.yml?logo=github)](https://github.com/JetBrains/jewel/actions/workflows/build.yml) [![Licensed under Apache 2.0](https://img.shields.io/github/license/JetBrains/jewel?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRiIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0ibTMgNiAzIDFtMCAwLTMgOWE1LjAwMiA1LjAwMiAwIDAgMCA2LjAwMSAwTTYgN2wzIDlNNiA3bDYtMm02IDIgMy0xbS0zIDEtMyA5YTUuMDAyIDUuMDAyIDAgMCAwIDYuMDAxIDBNMTggN2wzIDltLTMtOS02LTJtMC0ydjJtMCAxNlY1bTAgMTZIOW0zIDBoMyIvPjwvc3ZnPg==)](https://github.com/JetBrains/jewel/blob/main/LICENSE) [![Latest release](https://img.shields.io/github/v/release/JetBrains/jewel?include_prereleases&label=Latest%20Release&logo=github)](https://github.com/JetBrains/jewel/releases/latest) ![Compose for Desktop version](https://img.shields.io/badge/Compose%20for%20Desktop-1.6.0-dev1369?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB2aWV3Qm94PSIwIDAgNjcgNzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI%2BPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zNS45OTkgMi42NjNhNS4wMSA1LjAxIDAgMCAwLTQuOTk4IDBsLTI2LjUgMTUuMjUzYTQuOTk0IDQuOTk0IDAgMCAwLTEuMTk4Ljk2MmwxMS4xMDggNi4zNjZjLjI2OC0uMjkuNTgtLjU0LjkzMS0uNzQ0bDE2LjE1Ni05LjM0MmE0IDQgMCAwIDEgNC4wMDQgMEw1MS42NTcgMjQuNWMuMzUxLjIwMy42NjQuNDU1LjkzMi43NDRsMTEuMTA4LTYuMzY2YTQuOTkxIDQuOTkxIDAgMCAwLTEuMTk4LS45NjJsLTI2LjUtMTUuMjUzWm0yOC43MjMgMTcuOTMzLTExLjE4MyA2LjQwOGMuMDc2LjMxLjExNi42MzIuMTE2Ljk1OXYxNy43OTRhNCA0IDAgMCAxLTEuOTU4IDMuNDRsLTE2LjIzNSA5LjYzOGEzLjk5OCAzLjk5OCAwIDAgMS0uOTYyLjQxMnYxMi42M2E1LjAwNSA1LjAwNSAwIDAgMCAxLjQyOC0uNTY5bDI2LjYyLTE1LjczQTQuOTg2IDQuOTg2IDAgMCAwIDY1IDUxLjI4NFYyMi4yMzdjMC0uNTY3LS4wOTctMS4xMi0uMjc4LTEuNjRaTTIgMjIuMjM3YzAtLjU2Ny4wOTctMS4xMi4yNzgtMS42NGwxMS4xODMgNi40MDdjLS4wNzYuMzEtLjExNi42MzItLjExNi45NTl2MTguNjMzYTQgNCAwIDAgMCAyLjA4IDMuNTA5bDE2LjA3NCA4LjhjLjMyLjE3NC42NTYuMzAyIDEuMDAxLjM4NHYxMi42MzhhNS4wMDUgNS4wMDUgMCAwIDEtMS41MTctLjUzM0w0LjYwMyA1Ny4wMkE0Ljk4NyA0Ljk4NyAwIDAgMSAyIDUyLjY0MlYyMi4yMzdaTTMwLjAwMi45MzVhNy4wMTQgNy4wMTQgMCAwIDEgNi45OTYgMGwyNi41IDE1LjI1M0E2Ljk4IDYuOTggMCAwIDEgNjcgMjIuMjM4djI5LjA0N2E2Ljk4IDYuOTggMCAwIDEtMy40MzMgNi4wMDlsLTI2LjYyIDE1LjczMWE3LjAxNCA3LjAxNCAwIDAgMS02LjkyMy4xMkwzLjY0NCA1OC43NzFBNi45ODEgNi45ODEgMCAwIDEgMCA1Mi42NDFWMjIuMjM4YTYuOTggNi45OCAwIDAgMSAzLjUwMi02LjA1TDMwLjAwMi45MzZabS04LjYwNCAyNy41NTIgMTAuNTgyLTYuMTFjLjk0LS41NDIgMi4xLS41NDIgMy4wNCAwbDEwLjU4MiA2LjExYTIuOTk2IDIuOTk2IDAgMCAxIDEuNTAzIDIuNTkzdjExLjY1M2MwIDEuMDU2LS41NiAyLjAzNC0xLjQ3MyAyLjU3NmwtMTAuNjQzIDYuMzA4YTMuMDQ0IDMuMDQ0IDAgMCAxLTMuMDA5LjA1MmwtMTAuNTItNS43NWEyLjk5NiAyLjk5NiAwIDAgMS0xLjU2NS0yLjYyN1YzMS4wOGMwLTEuMDY4LjU3My0yLjA1NiAxLjUwMy0yLjU5M1oiIGZpbGw9IiNmZmYiLz48L3N2Zz4%3D)


# Jewel: a Compose for Desktop theme

<img alt="Jewel logo" src="art/jewel-logo.svg" width="20%"/>
Expand Down Expand Up @@ -56,14 +55,16 @@ dependencies {
implementation("org.jetbrains.jewel:jewel-ide-laf-bridge:[jewel version]-ij-[platform version]")
}
```

<br/>

> [!TIP]
> <a href="https://www.droidcon.com/2023/11/15/meet-jewelcreate-ide-plugins-in-compose/">
> <img src="https://i.vimeocdn.com/video/1749849437-f275e0337faca5cedab742ea157abbafe5a0207d3a59db891a72b6180ce13a6c-d?mh=120" align="left" />
> </a>
>
> If you want to learn more about Jewel and Compose for Desktop and why they're a great, modern solution for your desktop
> If you want to learn more about Jewel and Compose for Desktop and why they're a great, modern solution for your
> desktop
> UI needs, check out [this talk](https://www.droidcon.com/2023/11/15/meet-jewelcreate-ide-plugins-in-compose/) by Jewel
> contributors Sebastiano and Chris.
>
Expand Down Expand Up @@ -105,6 +106,46 @@ The project is split in modules:
The standalone theme can be used in any Compose for Desktop app. You use it as a normal theme, and you can customise it
to your heart's content. By default, it matches the official Int UI specs.

Your setup in `build.gradle.kts` should look something like this, assuming you use version catalogs:

```kotlin
plugins {
kotlin("jvm")
alias(libs.plugins.composeDesktop)
}

java {
toolchain {
vendor = JvmVendorSpec.JETBRAINS
languageVersion = 21
}
}

kotlin {
jvmToolchain {
vendor = JvmVendorSpec.JETBRAINS
languageVersion = 21
}
}

repositories {
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
mavenCentral()
}

dependencies {
implementation(libs.jewel.intUi.standalone)
implementation(libs.jewel.intUi.decoratedWindow) // Optional

implementation(compose.desktop.currentOs) {
// Exclude Material components — we don't need them
exclude(group = "org.jetbrains.compose.material")
}
}
```

For further information, you can refer to the [`standalone` sample](samples/standalone/build.gradle.kts).

> [!WARNING]
> Note that Jewel **requires** the JetBrains Runtime to work correctly. Some features like font loading depend on it,
> as it has extra features and patches for UI functionalities that aren't available in other JDKs.
Expand Down Expand Up @@ -151,7 +192,7 @@ IntUiTheme(
}
```

### The Swing Bridge
### Running on the IntelliJ Platform: the Swing bridge

Jewel includes a crucial element for proper integration with the IDE: a bridge between the Swing components — theme
and LaF — and the Compose world.
Expand All @@ -173,6 +214,69 @@ SwingBridgeTheme {
}
```

#### Supported IntelliJ Platform versions

To use Jewel in the IntelliJ Platform, you should depend on the appropriate `ide-laf-bridge-*` artifact, which will
bring in the necessary transitive dependencies.

| IntelliJ Platform version(s) | Artifact to use |
|------------------------------|----------------------|
| 2023.3 and 2024.1 | `ide-laf-bridge-233` |
| 2023.2 | `ide-laf-bridge-232` |
| 2023.1 or older | **Not supported** |

> [!CAUTION]
> In the IntelliJ Platform 2024.1, to be able to use Jewel, you need to shadow both Jewel and Compose, due to
> potential clashes with the versions bundled in the platform. You can use the
> [Package Search plugin](https://github.com/JetBrains/package-search-intellij-plugin) as a reference on how to do it.

Your setup in `build.gradle.kts` should look something like this, assuming you use version catalogs:

```kotlin
plugins {
kotlin("jvm")
alias(libs.plugins.composeDesktop)
alias(libs.plugins.ideaGradlePlugin)
}

java {
toolchain {
vendor = JvmVendorSpec.JETBRAINS
languageVersion = 17 // Or 21, if you're targeting IJ 2024.1 or later
}
}

kotlin {
jvmToolchain {
vendor = JvmVendorSpec.JETBRAINS
languageVersion = 17 // Or 21, if you're targeting IJ 2024.1 or later
}
}

repositories {
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
maven("https://www.jetbrains.com/intellij-repository/snapshots")
maven("https://www.jetbrains.com/intellij-repository/releases")
maven("https://cache-redirector.jetbrains.com/intellij-dependencies")
mavenCentral()
}

dependencies {
implementation(libs.jewel.ideLafBridge) {
// Exclude any coroutines dependency that might be coming through — the IDE has its own
exclude(group = "org.jetbrains.kotlinx")
}

implementation(compose.desktop.currentOs) {
// Exclude Material components — we don't need them
exclude(group = "org.jetbrains.compose.material")
exclude(group = "org.jetbrains.kotlinx")
}
}
```

For further information, you can refer to the [`ide-plugin` sample](samples/ide-plugin/build.gradle.kts).

#### Accessing icons

When you want to draw an icon from the resources, you can either use the `Icon` composable and pass it the resource path
Expand Down Expand Up @@ -242,6 +346,7 @@ right path based on the state. If you want to learn more about this system, look
implementations.

### Fonts

To load a system font, you can obtain it by its family name:

```kotlin
Expand Down Expand Up @@ -291,7 +396,9 @@ you. However, if you want to also enable it in other scenarios and in standalone
> runtime to fix. Once the required changes are made in the JetBrains Runtime, we'll remove this notice.

## Written with Jewel

Here is a small selection of projects that use Compose for Desktop and Jewel:

* [Package Search](https://github.com/JetBrains/package-search-intellij-plugin) (IntelliJ Platform plugin)
* [Kotlin Explorer](https://github.com/romainguy/kotlin-explorer) (standalone app)
* ...and more to come!
Expand Down
13 changes: 5 additions & 8 deletions buildSrc/src/main/kotlin/IdeaConfiguration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ import org.gradle.api.provider.Property
import org.gradle.jvm.toolchain.JavaLanguageVersion
import java.util.concurrent.atomic.AtomicBoolean

enum class SupportedIJVersion {
IJ_232,
IJ_233
}

private var warned = AtomicBoolean(false)

fun Project.supportedIJVersion(): SupportedIJVersion {
Expand All @@ -20,21 +15,23 @@ fun Project.supportedIJVersion(): SupportedIJVersion {
if (!warned.getAndSet(true)) {
logger.warn(
"""
No 'supported.ij.version' property provided. Falling back to IJ 233.
No 'supported.ij.version' property provided. Falling back to IJ 241.
It is recommended to provide it using the local.properties file or
-Psupported.ij.version to avoid unexpected behavior.
""".trimIndent()
)
}
return SupportedIJVersion.IJ_233
return SupportedIJVersion.IJ_241
}

return when (prop) {
"232" -> SupportedIJVersion.IJ_232
"233" -> SupportedIJVersion.IJ_233
"241" -> SupportedIJVersion.IJ_241
else -> error(
"Invalid 'supported.ij.version' with value '$prop' is provided. " +
"It should be one of these values: ('232', '233')"
"It should be one of these values: " +
SupportedIJVersion.values().joinToString(", ") { it.rawPlatformVersion }
)
}
}
Expand Down
15 changes: 15 additions & 0 deletions buildSrc/src/main/kotlin/SupportedIJVersion.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
enum class SupportedIJVersion(
/** Human-readable major platform version. E.g., `2023.3` */
val majorPlatformVersion: String,
/** Raw major platform version. E.g., `233` */
val rawPlatformVersion: String,
/** If true, this platform version has its dedicated bridge artifact. */
val hasBridgeArtifact: Boolean,
/** The JDK version to use. */
val jdkVersion: Int,
) {

IJ_232("2023.2", "232", true, 17),
IJ_233("2023.3", "233", true, 17),
IJ_241("2024.1", "241", false, 17),
}
28 changes: 16 additions & 12 deletions buildSrc/src/main/kotlin/jewel-ij-publish.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@file:Suppress("UnstableApiUsage")

import SupportedIJVersion.IJ_232
import SupportedIJVersion.IJ_233
import gradle.kotlin.dsl.accessors._7527f81e50bfbc9f72561cc0d0801284.dokkaHtml
import gradle.kotlin.dsl.accessors._7527f81e50bfbc9f72561cc0d0801284.kotlin
import gradle.kotlin.dsl.accessors._7527f81e50bfbc9f72561cc0d0801284.main
import gradle.kotlin.dsl.accessors._7527f81e50bfbc9f72561cc0d0801284.publishing

plugins {
kotlin("jvm")
Expand All @@ -25,17 +27,19 @@ publishing {
configureJewelRepositories()

publications {
register<MavenPublication>("IdeMain") {
from(components["kotlin"])
artifact(javadocJar)
artifact(sourcesJar)
val ijVersionRaw = when (supportedIJVersion()) {
IJ_232 -> "232"
IJ_233 -> "233"
val ijpVersion = supportedIJVersion()

if (ijpVersion.hasBridgeArtifact) {
register<MavenPublication>("IdeMain") {
from(components["kotlin"])
artifact(javadocJar)
artifact(sourcesJar)

val ijVersionRaw = ijpVersion.rawPlatformVersion
version = project.version.toString().withVersionSuffix("ij-$ijVersionRaw")
artifactId = "jewel-${project.name}"
pom { configureJewelPom() }
}
version = project.version.toString().withVersionSuffix("ij-$ijVersionRaw")
artifactId = "jewel-${project.name}"
pom { configureJewelPom() }
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/jewel.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ version = when {
java {
toolchain {
vendor = JvmVendorSpec.JETBRAINS
languageVersion = 17
languageVersion = supportedIJVersion().jdkVersion
}
}

kotlin {
jvmToolchain {
vendor = JvmVendorSpec.JETBRAINS
languageVersion = 17
languageVersion = supportedIJVersion().jdkVersion
}

target {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,9 @@ open class CheckIdeaVersionTask : DefaultTask() {
group = "jewel"

val currentPlatformVersion = project.supportedIJVersion()
enabled = project.name.endsWith(getPlatformSuffix(currentPlatformVersion))
enabled = project.name.endsWith(currentPlatformVersion.rawPlatformVersion)
}

private fun getPlatformSuffix(currentPlatformVersion: SupportedIJVersion) =
when (currentPlatformVersion) {
SupportedIJVersion.IJ_232 -> "232"
SupportedIJVersion.IJ_233 -> "233"
}

@TaskAction
fun generate() {
val json = Json {
Expand Down Expand Up @@ -62,7 +56,7 @@ open class CheckIdeaVersionTask : DefaultTask() {
check(icReleases.releases.isNotEmpty()) { "Was expecting to have releases but the list is empty" }

val currentPlatformVersion = project.supportedIJVersion()
val majorPlatformVersion = getRawPlatformVersion(currentPlatformVersion)
val majorPlatformVersion = currentPlatformVersion.majorPlatformVersion
val rawPlatformBuild = readPlatformBuild(currentPlatformVersion)

val isCurrentBuildStable = !rawPlatformBuild.contains("EAP")
Expand Down Expand Up @@ -92,19 +86,9 @@ open class CheckIdeaVersionTask : DefaultTask() {
logger.lifecycle("No IntelliJ Platform version updates available. Current: $currentPlatformBuild")
}

private fun getRawPlatformVersion(currentPlatformVersion: SupportedIJVersion) =
when (currentPlatformVersion) {
SupportedIJVersion.IJ_232 -> "2023.2"
SupportedIJVersion.IJ_233 -> "2023.3"
}

private fun readPlatformBuild(platformVersion: SupportedIJVersion): String {
val catalogFile = project.rootProject.file("gradle/libs.versions.toml")
val dependencyName =
when (platformVersion) {
SupportedIJVersion.IJ_232 -> "idea232"
SupportedIJVersion.IJ_233 -> "idea233"
}
val dependencyName = "idea${platformVersion.rawPlatformVersion}"

val catalogDependencyLine =
catalogFile.useLines { lines -> lines.find { it.startsWith(dependencyName) } }
Expand Down
18 changes: 12 additions & 6 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
[versions]
composeDesktop = "1.6.0-dev1369"
detekt = "1.23.1"
composeDesktop = "1.6.0-dev1397"
detekt = "1.23.4"
dokka = "1.8.20"
idea232 = "232.10227.8"
idea233 = "233.13135.103"
ideaGradlePlugin = "1.16.1"
jna = "5.13.0"
idea233 = "233.14015.106"
idea241 = "241.9959.31-EAP-SNAPSHOT"
ideaGradlePlugin = "1.17.0"
jna = "5.14.0"
kotlin = "1.8.21"
kotlinSarif = "0.4.0"
kotlinpoet = "1.14.2"
kotlinterGradlePlugin = "3.16.0"
kotlinxSerialization = "1.5.1"
kotlinxBinaryCompat = "0.13.2"
kotlinxBinaryCompat = "0.14.0"
poko = "0.13.1"

[libraries]
Expand All @@ -27,6 +28,10 @@ ij-platform-ide-core-233 = { module = "com.jetbrains.intellij.platform:ide-core"
ij-platform-ide-impl-233 = { module = "com.jetbrains.intellij.platform:ide-impl", version.ref = "idea233" }
ij-platform-core-ui-233 = { module = "com.jetbrains.intellij.platform:core-ui", version.ref = "idea233" }

ij-platform-ide-core-241 = { module = "com.jetbrains.intellij.platform:ide-core", version.ref = "idea241" }
ij-platform-ide-impl-241 = { module = "com.jetbrains.intellij.platform:ide-impl", version.ref = "idea241" }
ij-platform-core-ui-241 = { module = "com.jetbrains.intellij.platform:core-ui", version.ref = "idea241" }

jna-core = { module = "net.java.dev.jna:jna", version.ref = "jna" }

# Plugin libraries for build-logic's convention plugins to use to resolve the types/tasks coming from these plugins
Expand All @@ -41,6 +46,7 @@ poko-gradlePlugin = { module = "dev.drewhamilton.poko:poko-gradle-plugin", versi
[bundles]
idea232 = ["ij-platform-ide-core-232", "ij-platform-ide-impl-232", "ij-platform-core-ui-232"]
idea233 = ["ij-platform-ide-core-233", "ij-platform-ide-impl-233", "ij-platform-core-ui-233"]
idea241 = ["ij-platform-ide-core-241", "ij-platform-ide-impl-241", "ij-platform-core-ui-241"]

[plugins]
composeDesktop = { id = "org.jetbrains.compose", version.ref = "composeDesktop" }
Expand Down
Loading
Loading