[go: nahoru, domu]

blob: 43b3ce56af6ac1174088011bf2cbd9a7ddbb6d45 [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.desktop.ui.tooling.preview.runtime
import androidx.compose.runtime.Composable
import androidx.compose.runtime.currentComposer
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.platform.TestComposeWindow
import androidx.compose.ui.unit.Density
/**
* This class is used by Compose Desktop Intellij plugin
* for the non-interactive preview functionality.
*
* The class is used via reflection.
*
* The non-interactive preview for desktop works in the following way:
* 1. A user annotates a composable function with the @Preview annotation;
* 2. A user is able to request an IDE preview by clicking a gutter icon in the editor;
* 3. When an updated preview is requested, the Intellij plugin requests a fresh build from Gradle
* and pulls an updated preview configuration from the build;
* 4. The IDE plugin manages a separate preview host process;
* 5. The IDE plugin requests a new frame from the preview host process, when needed (either when
* a user requests it explicitly or by resizing the preview tool window);
* 6. When the preview process receives a preview request, it renders a new frame using this
* facade in an isolated classloader via reflection. The classloader is persisted between
* requests to minimize render time. Currently it is reused only if there are no changes in a
* preview classpath (a requested preview function or a requested frame size may differ).
* 7. A rendered frame is sent back to the IDE plugin and is shown in the IDE as an image.
*/
@Suppress("DEPRECATION", "unused")
internal class NonInteractivePreviewFacade {
companion object {
@JvmStatic
@OptIn(ExperimentalComposeUiApi::class)
fun render(fqName: String, width: Int, height: Int, scale: Double?): ByteArray {
val className = fqName.substringBeforeLast(".")
val methodName = fqName.substringAfterLast(".")
val density = scale?.let { Density(it.toFloat()) } ?: Density(1f)
val window = TestComposeWindow(width = width, height = height, density = density)
window.setContent @Composable {
// We need to delay the reflection instantiation of the class until we are in the
// composable to ensure all the right initialization has happened and the Composable
// class loads correctly.
androidx.compose.ui.tooling.ComposableInvoker.invokeComposable(
className,
methodName,
currentComposer
)
}
return window.surface.makeImageSnapshot().encodeToData()!!.bytes
}
}
}