Skip to content

Commit

Permalink
Update README for 0.8.0
Browse files Browse the repository at this point in the history
Added code samples, updated project structure, added sections on custom
window decoration and icon runtime patching.
  • Loading branch information
rock3r committed Oct 22, 2023
1 parent 3f8aab6 commit 932b1ae
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 24 deletions.
138 changes: 114 additions & 24 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)](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)](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)


# Jewel: a Compose for Desktop theme

<img alt="Jewel logo" src="art/jewel-logo.svg" width="20%"/>
Expand All @@ -10,11 +9,14 @@ desktop-optimized theme and set of components.

> [!WARNING]
>
> This project is in active development, and caution is advised when considering it for production uses. You _can_,
> but you should expect APIs to change often, things to move around and/or break, and all that jazz. Binary
> compatibility is not currently guaranteed across releases, but it is an eventual aim for 1.0, if it is possible.
> This project is in active development, and caution is advised when considering it for production uses. You _can_ use
> it, but you should expect APIs to change often, things to move around and/or break, and all that jazz. Binary
> compatibility is not guaranteed across releases, and APIs are still in flux and subject to change.
>
> Writing 3rd party IntelliJ Plugins in Compose for Desktop is currently **not officially supported** by the IntelliJ
> Platform. It should work, but your mileage may vary, and if things break you're on your own.
>
> Use at your own risk! (but have fun if you do!)
> Use at your own risk!
Jewel provides stand-alone implementations of the IntelliJ Platform themes that can be used in any Compose for Desktop
application, and a Swing LaF Bridge that only works in the IntelliJ Platform (i.e., used to create IDE plugins), but
Expand All @@ -26,15 +28,27 @@ The project is split in modules:

1. `buildSrc` contains the build logic, including:
* The `jewel` and `jewel-publish` configuration plugins
* The `jewel-check-public-api` and `jewel-linting` configuration plugins
* The Theme Palette generator plugin
2. `core` contains the foundational Jewel functionality, including the components and their styling primitives
3. `int-ui` implements the standalone version of the IntelliJ New UI, which implements the
["Int UI" design system](https://www.figma.com/community/file/1227732692272811382/int-ui-kit), and can be used
anywhere
4. `ide-laf-bridge` contains the Swing LaF bridge to use in IntelliJ Platform plugins (see more below)
5. `samples` contains the example apps, which showcase the available components:
1. `standalone` is a regular CfD app, using the predefined "base" theme definitions
2. `ide-plugin` is an IntelliJ plugin, adding some UI to the IDE, and showcasing the use of the Swing Bridge
* The Studio Releases generator plugin
2. `foundation` contains the foundational Jewel functionality:
* Basic components without strong styling (e.g., `SelectableLazyColumn`, `BasicLazyTree`)
* The `JewelTheme` interface with a few basic composition locals
* The state management primitives
* The Jewel annotations
* A few other primitives
3. `ui` contains all the styled components and custom painters logic
4. `decorated-window` contains basic, unstyled functionality to have custom window decoration on the JetBrains Runtime
5. `int-ui` contains two modules:
* `int-ui-standalone` has a standalone version of the Int UI styling values that can be used in any Compose for
Desktop app
* `int-ui-decorated-window` has a standalone version of the Int UI styling values for the custom window decoration
that can be used in any Compose for Desktop app
5. `ide-laf-bridge` contains the Swing LaF bridge to use in IntelliJ Platform plugins (see more below)
* The `ide-laf-bridge-*` sub-modules contain code that is specific to a certain IntelliJ Platform version
6. `samples` contains the example apps, which showcase the available components:
* `standalone` is a regular CfD app, using the standalone theme definitions and custom window decoration
* `ide-plugin` is an IntelliJ plugin that showcases the use of the Swing Bridge

### Int UI Standalone theme

Expand All @@ -46,31 +60,107 @@ to your heart's content. By default, it matches the official Int UI specs.
> as it has extra features and patches for UI functionalities that aren't available in other JDKs.
> We **do not support** running Jewel on any other JDK.
To use Jewel components in a non-IntelliJ Platform environment, you need to wrap your UI hierarchy in a `IntUiTheme`
composable:

```kotlin
IntUiTheme(isDark = false) {
// ...
}
```
If you want more control over the theming, you can use other `IntUiTheme` overloads, like the standalone sample does.

#### Custom window decoration
The JetBrains Runtime allows windows to have a custom decoration instead of the regular title bar.

![A screenshot of the custom window decoration in the standalone sample](art/docs/custom-chrome.png)

The standalone sample app shows how to easily get something that looks like a JetBrains IDE; if you want to go _very_
custom, you only need to depend on the `decorated-window` module, which contains all the required primitives, but not
the Int UI styling.

To get an IntelliJ-like custom title bar, you need to pass the window decoration styling to your theme call, and add the
`DecoratedWindow` composable at the top level of the theme:

```kotlin
IntUiTheme(
themeDefinition,
componentStyling = {
themeDefinition.decoratedWindowComponentStyling(
titleBarStyle = TitleBarStyle.light()
)
},
) {
DecoratedWindow(
onCloseRequest = { exitApplication() },
) {
// ...
}
}
```

### 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.
Jewel includes a crucial element for proper integration with the IDE: a bridge between the Swing components theme
and LaF and the Compose world.

This bridge ensures that we pick up the colours, typography, metrics, and images as defined in the current IntelliJ
theme, and apply them to the Compose components as well — at least for themes that use the
standard [IntelliJ theming](https://plugins.jetbrains.com/docs/intellij/themes-getting-started.html) mechanisms.
theme, and apply them to the Compose components as well. This means Jewel will automatically adapt to IntelliJ Platform
themes that use the [standard theming](https://plugins.jetbrains.com/docs/intellij/themes-getting-started.html) mechanisms.

> [!NOTE]
> IntelliJ themes that use non-standard mechanisms (such as providing custom UI implementations for Swing components)
> are not, and will never, be supported.
> are not, and can never, be supported.
If you're writing an IntelliJ Platform plugin, you should use the `SwingBridgeTheme` instead of a standalone theme.
If you're writing an IntelliJ Platform plugin, you should use the `SwingBridgeTheme` instead of the standalone theme:

```kotlin
SwingBridgeTheme {
// ...
}
```

#### Accessing icons

When you want to draw an icon from the resources, you should use a `PainterProvider`. Reading an icon from the IDE is
as easy as using the `retrieveStatefulIcon()` and `retrieveStatelessIcon()`:
When you want to draw an icon from the resources, you can either use the `Icon` composable and pass it the resource path
and the corresponding class to look up the classpath from, or go one lever deeper and use the lower level,
`Painter`-based API.

The `Icon` approach looks like this:

```kotlin
val svgLoader = service<SwingBridgeService>().svgLoader
val painterProvider = retrieveStatelessIcon("icons/bot-toolwindow.svg", svgLoader, iconData)
// Load the "close" icon from the IDE's AllIcons class
Icon(
"actions/close.svg",
iconClass = AllIcons::class.java,
contentDescription = "Close",
)
```

To obtain a `Painter`, instead, you'd use:

```kotlin
val painterProvider = rememberResourcePainterProvider(
path = "actions/close.svg",
iconClass = AllIcons::class.java
)
val painter by painterProvider.getPainter()
```

#### Icon runtime patching
Jewel emulates the under-the-hood machinations that happen in the IntelliJ Platform when loading icons. Specifically,
the resource will be subject to some transformations before being loaded.

For example, in the IDE, if New UI is active, the icon path may be replaced with a different one. Some key colors in SVG
icons will also be replaced based on the current theme. See
[the docs](https://plugins.jetbrains.com/docs/intellij/work-with-icons-and-images.html#new-ui-icons).

Beyond that, even in standalone, Jewel will pick up icons with the appropriate dark/light variant for the current theme,
and for bitmap icons it will try to pick the 2x variants based on the `LocalDensity`.

If you want to learn more about this system, the entry point is the `PainterHint` class.

### Swing interoperability

As this is Compose for Desktop, you get a good degree of interoperability with Swing. To avoid glitches and z-order
Expand All @@ -79,7 +169,7 @@ issues, you should enable the
before you initialize Compose content.

The `ToolWindow.addComposeTab()` extension function provided by the `ide-laf-bridge` module will take care of that for
you, but if you want to also enable it in other scenarios and in standalone applications, you can call the
you. However, if you want to also enable it in other scenarios and in standalone applications, you can call the
`enableNewSwingCompositing()` function in your Compose entry points (that is, right before creating a `ComposePanel`).

> [!NOTE]
Expand Down
Binary file added art/docs/custom-chrome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 932b1ae

Please sign in to comment.