Browse Source

Codeviewer. Migrate to build154

pull/395/head
Igor Demin 4 years ago
parent
commit
e25d74d457
  1. 7
      examples/codeviewer/android/build.gradle.kts
  2. 2
      examples/codeviewer/android/src/main/java/org/jetbrains/codeviewer/MainActivity.kt
  3. 4
      examples/codeviewer/build.gradle.kts
  4. 23
      examples/codeviewer/common/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt
  5. 19
      examples/codeviewer/common/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Selection.kt
  6. 6
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt
  7. 6
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Selection.kt
  8. 13
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/CodeViewerView.kt
  9. 1
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/Editor.kt
  10. 6
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorEmptyView.kt
  11. 20
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorTabsView.kt
  12. 22
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorView.kt
  13. 28
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/filetree/FileTreeView.kt
  14. 10
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/statusbar/StatusBar.kt
  15. 33
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/LazyColumnFor.kt
  16. 19
      examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt
  17. 6
      examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt
  18. 15
      examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt
  19. 9
      examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Selection.kt
  20. 11
      examples/codeviewer/desktop/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt

7
examples/codeviewer/android/build.gradle.kts

@ -22,4 +22,11 @@ android {
dependencies { dependencies {
implementation(project(":common")) implementation(project(":common"))
implementation("androidx.activity:activity-compose:1.3.0-alpha02") {
exclude(group = "androidx.compose.animation")
exclude(group = "androidx.compose.foundation")
exclude(group = "androidx.compose.material")
exclude(group = "androidx.compose.runtime")
exclude(group = "androidx.compose.ui")
}
} }

2
examples/codeviewer/android/src/main/java/org/jetbrains/codeviewer/MainActivity.kt

@ -1,8 +1,8 @@
package org.jetbrains.codeviewer package org.jetbrains.codeviewer
import android.os.Bundle import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.ui.platform.setContent
import org.jetbrains.codeviewer.platform._HomeFolder import org.jetbrains.codeviewer.platform._HomeFolder
import org.jetbrains.codeviewer.ui.MainView import org.jetbrains.codeviewer.ui.MainView
import java.io.File import java.io.File

4
examples/codeviewer/build.gradle.kts

@ -9,10 +9,10 @@ buildscript {
dependencies { dependencies {
// __LATEST_COMPOSE_RELEASE_VERSION__ // __LATEST_COMPOSE_RELEASE_VERSION__
classpath("org.jetbrains.compose:compose-gradle-plugin:0.3.0-build148") classpath("org.jetbrains.compose:compose-gradle-plugin:0.3.0-build154")
classpath("com.android.tools.build:gradle:4.0.1") classpath("com.android.tools.build:gradle:4.0.1")
// __KOTLIN_COMPOSE_VERSION__ // __KOTLIN_COMPOSE_VERSION__
classpath(kotlin("gradle-plugin", version = "1.4.21-2")) classpath(kotlin("gradle-plugin", version = "1.4.30"))
} }
} }

23
examples/codeviewer/common/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt

@ -1,31 +1,14 @@
package org.jetbrains.codeviewer.platform package org.jetbrains.codeviewer.platform
import android.graphics.BitmapFactory
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.AmbientContext
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import java.io.InputStream
import java.net.URL
@Composable
actual fun imageResource(res: String): ImageBitmap {
val context = AmbientContext.current
val id = context.resources.getIdentifier(res, "drawable", context.packageName)
return androidx.compose.ui.res.imageResource(id)
}
actual suspend fun imageFromUrl(url: String): ImageBitmap {
val bytes = URL(url).openStream().buffered().use(InputStream::readBytes)
return BitmapFactory.decodeByteArray(bytes, 0, bytes.size).asImageBitmap()
}
@Composable @Composable
actual fun Font(name: String, res: String, weight: FontWeight, style: FontStyle): Font { actual fun Font(name: String, res: String, weight: FontWeight, style: FontStyle): Font {
val context = AmbientContext.current val context = LocalContext.current
val id = context.resources.getIdentifier(res, "font", context.packageName) val id = context.resources.getIdentifier(res, "font", context.packageName)
return androidx.compose.ui.text.font.Font(id, weight, style) return Font(id, weight, style)
} }

19
examples/codeviewer/common/src/androidMain/kotlin/org/jetbrains/codeviewer/platform/Selection.kt

@ -1,19 +0,0 @@
package org.jetbrains.codeviewer.platform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.selection.Selection
import androidx.compose.ui.selection.SelectionContainer
import androidx.compose.ui.text.InternalTextApi
@OptIn(InternalTextApi::class)
@Composable
actual fun SelectionContainer(children: @Composable () -> Unit) {
val selection = remember { mutableStateOf<Selection?>(null) }
SelectionContainer(
selection = selection.value,
onSelectionChange = { selection.value = it },
children = children
)
}

6
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt

@ -1,15 +1,9 @@
package org.jetbrains.codeviewer.platform package org.jetbrains.codeviewer.platform
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@Composable
expect fun imageResource(res: String): ImageBitmap
expect suspend fun imageFromUrl(url: String): ImageBitmap
@Composable @Composable
expect fun Font(name: String, res: String, weight: FontWeight, style: FontStyle): Font expect fun Font(name: String, res: String, weight: FontWeight, style: FontStyle): Font

6
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/platform/Selection.kt

@ -1,6 +0,0 @@
package org.jetbrains.codeviewer.platform
import androidx.compose.runtime.Composable
@Composable
expect fun SelectionContainer(children: @Composable () -> Unit)

13
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/CodeViewerView.kt

@ -1,12 +1,13 @@
package org.jetbrains.codeviewer.ui package org.jetbrains.codeviewer.ui
import androidx.compose.animation.animate
import androidx.compose.animation.core.Spring.StiffnessLow import androidx.compose.animation.core.Spring.StiffnessLow
import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.SpringSpec
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.AmbientContentColor
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowForward import androidx.compose.material.icons.filled.ArrowForward
@ -31,10 +32,10 @@ fun CodeViewerView(model: CodeViewer) {
val animatedSize = if (panelState.splitter.isResizing) { val animatedSize = if (panelState.splitter.isResizing) {
if (panelState.isExpanded) panelState.expandedSize else panelState.collapsedSize if (panelState.isExpanded) panelState.expandedSize else panelState.collapsedSize
} else { } else {
animate( animateDpAsState(
if (panelState.isExpanded) panelState.expandedSize else panelState.collapsedSize, if (panelState.isExpanded) panelState.expandedSize else panelState.collapsedSize,
SpringSpec(stiffness = StiffnessLow) SpringSpec(stiffness = StiffnessLow)
) ).value
} }
VerticalSplittable( VerticalSplittable(
@ -82,7 +83,7 @@ private fun ResizablePanel(
state: PanelState, state: PanelState,
content: @Composable () -> Unit, content: @Composable () -> Unit,
) { ) {
val alpha = animate(if (state.isExpanded) 1f else 0f, SpringSpec(stiffness = StiffnessLow)) val alpha by animateFloatAsState(if (state.isExpanded) 1f else 0f, SpringSpec(stiffness = StiffnessLow))
Box(modifier) { Box(modifier) {
Box(Modifier.fillMaxSize().graphicsLayer(alpha = alpha)) { Box(Modifier.fillMaxSize().graphicsLayer(alpha = alpha)) {
@ -92,7 +93,7 @@ private fun ResizablePanel(
Icon( Icon(
if (state.isExpanded) Icons.Default.ArrowBack else Icons.Default.ArrowForward, if (state.isExpanded) Icons.Default.ArrowBack else Icons.Default.ArrowForward,
contentDescription = if (state.isExpanded) "Collapse" else "Expand", contentDescription = if (state.isExpanded) "Collapse" else "Expand",
tint = AmbientContentColor.current, tint = LocalContentColor.current,
modifier = Modifier modifier = Modifier
.padding(top = 4.dp) .padding(top = 4.dp)
.width(24.dp) .width(24.dp)

1
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/Editor.kt

@ -45,6 +45,7 @@ fun Editor(file: File) = Editor(
fun content(index: Int): Editor.Content { fun content(index: Int): Editor.Content {
val text = textLines.get(index) val text = textLines.get(index)
.trim('\r', '\n') // fix for native crash in skia
val state = mutableStateOf(text) val state = mutableStateOf(text)
return Editor.Content(state, isCode) return Editor.Content(state, isCode)
} }

6
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorEmptyView.kt

@ -4,8 +4,8 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.AmbientContentColor
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Code import androidx.compose.material.icons.filled.Code
@ -21,13 +21,13 @@ fun EditorEmptyView() = Box(Modifier.fillMaxSize()) {
Icon( Icon(
Icons.Default.Code, Icons.Default.Code,
contentDescription = null, contentDescription = null,
tint = AmbientContentColor.current.copy(alpha = 0.60f), tint = LocalContentColor.current.copy(alpha = 0.60f),
modifier = Modifier.align(Alignment.CenterHorizontally) modifier = Modifier.align(Alignment.CenterHorizontally)
) )
Text( Text(
"To view file open it from the file tree", "To view file open it from the file tree",
color = AmbientContentColor.current.copy(alpha = 0.60f), color = LocalContentColor.current.copy(alpha = 0.60f),
fontSize = 20.sp, fontSize = 20.sp,
modifier = Modifier.align(Alignment.CenterHorizontally).padding(16.dp) modifier = Modifier.align(Alignment.CenterHorizontally).padding(16.dp)
) )

20
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorTabsView.kt

@ -1,19 +1,21 @@
package org.jetbrains.codeviewer.ui.editor package org.jetbrains.codeviewer.ui.editor
import androidx.compose.animation.animate
import androidx.compose.foundation.ScrollableRow
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.AmbientContentColor import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -22,7 +24,7 @@ import androidx.compose.ui.unit.sp
import org.jetbrains.codeviewer.ui.common.AppTheme import org.jetbrains.codeviewer.ui.common.AppTheme
@Composable @Composable
fun EditorTabsView(model: Editors) = ScrollableRow { fun EditorTabsView(model: Editors) = Row(Modifier.horizontalScroll(rememberScrollState())) {
for (editor in model.editors) { for (editor in model.editors) {
EditorTabView(editor) EditorTabView(editor)
} }
@ -30,15 +32,15 @@ fun EditorTabsView(model: Editors) = ScrollableRow {
@Composable @Composable
fun EditorTabView(model: Editor) = Surface( fun EditorTabView(model: Editor) = Surface(
color = animate(if (model.isActive) { color = if (model.isActive) {
AppTheme.colors.backgroundDark AppTheme.colors.backgroundDark
} else { } else {
Color.Transparent Color.Transparent
}) }
) { ) {
Row( Row(
Modifier Modifier
.clickable { .clickable(remember(::MutableInteractionSource), indication = null) {
model.activate() model.activate()
} }
.padding(4.dp), .padding(4.dp),
@ -46,7 +48,7 @@ fun EditorTabView(model: Editor) = Surface(
) { ) {
Text( Text(
model.fileName, model.fileName,
color = AmbientContentColor.current, color = LocalContentColor.current,
fontSize = 12.sp, fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 4.dp) modifier = Modifier.padding(horizontal = 4.dp)
) )
@ -56,7 +58,7 @@ fun EditorTabView(model: Editor) = Surface(
if (close != null) { if (close != null) {
Icon( Icon(
Icons.Default.Close, Icons.Default.Close,
tint = AmbientContentColor.current, tint = LocalContentColor.current,
contentDescription = "Close", contentDescription = "Close",
modifier = Modifier modifier = Modifier
.size(24.dp) .size(24.dp)

22
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorView.kt

@ -2,9 +2,14 @@ package org.jetbrains.codeviewer.ui.editor
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.selection.DisableSelection import androidx.compose.foundation.text.selection.DisableSelection
import androidx.compose.material.* import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.key import androidx.compose.runtime.key
@ -12,19 +17,16 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.platform.AmbientDensity
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import org.jetbrains.codeviewer.platform.SelectionContainer
import org.jetbrains.codeviewer.platform.VerticalScrollbar import org.jetbrains.codeviewer.platform.VerticalScrollbar
import org.jetbrains.codeviewer.ui.common.AppTheme import org.jetbrains.codeviewer.ui.common.AppTheme
import org.jetbrains.codeviewer.ui.common.Fonts import org.jetbrains.codeviewer.ui.common.Fonts
import org.jetbrains.codeviewer.ui.common.Settings import org.jetbrains.codeviewer.ui.common.Settings
import org.jetbrains.codeviewer.util.LazyColumnFor
import org.jetbrains.codeviewer.util.loadableScoped import org.jetbrains.codeviewer.util.loadableScoped
import org.jetbrains.codeviewer.util.withoutWidthConstraints import org.jetbrains.codeviewer.util.withoutWidthConstraints
import kotlin.text.Regex.Companion.fromLiteral import kotlin.text.Regex.Companion.fromLiteral
@ -65,7 +67,7 @@ fun EditorView(model: Editor, settings: Settings) = key(model) {
} }
@Composable @Composable
private fun Lines(lines: Editor.Lines, settings: Settings) = with(AmbientDensity.current) { private fun Lines(lines: Editor.Lines, settings: Settings) = with(LocalDensity.current) {
val maxNum = remember(lines.lineNumberDigitCount) { val maxNum = remember(lines.lineNumberDigitCount) {
(1..lines.lineNumberDigitCount).joinToString(separator = "") { "9" } (1..lines.lineNumberDigitCount).joinToString(separator = "") { "9" }
} }
@ -74,16 +76,16 @@ private fun Lines(lines: Editor.Lines, settings: Settings) = with(AmbientDensity
val scrollState = rememberLazyListState() val scrollState = rememberLazyListState()
val lineHeight = settings.fontSize.toDp() * 1.6f val lineHeight = settings.fontSize.toDp() * 1.6f
LazyColumnFor( LazyColumn(
lines.size,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
state = scrollState, state = scrollState
itemContent = { index -> ) {
items(lines.size) { index ->
Box(Modifier.height(lineHeight)) { Box(Modifier.height(lineHeight)) {
Line(Modifier.align(Alignment.CenterStart), maxNum, lines[index], settings) Line(Modifier.align(Alignment.CenterStart), maxNum, lines[index], settings)
} }
} }
) }
VerticalScrollbar( VerticalScrollbar(
Modifier.align(Alignment.CenterEnd), Modifier.align(Alignment.CenterEnd),

28
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/filetree/FileTreeView.kt

@ -2,10 +2,10 @@ package org.jetbrains.codeviewer.ui.filetree
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumnFor import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.AmbientContentColor
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@ -17,7 +17,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.AmbientDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
@ -35,7 +35,7 @@ fun FileTreeViewTabView() = Surface {
) { ) {
Text( Text(
"Files", "Files",
color = AmbientContentColor.current.copy(alpha = 0.60f), color = LocalContentColor.current.copy(alpha = 0.60f),
fontSize = 12.sp, fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 4.dp) modifier = Modifier.padding(horizontal = 4.dp)
) )
@ -46,18 +46,20 @@ fun FileTreeViewTabView() = Surface {
fun FileTreeView(model: FileTree) = Surface( fun FileTreeView(model: FileTree) = Surface(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
with(AmbientDensity.current) { with(LocalDensity.current) {
Box { Box {
val scrollState = rememberLazyListState() val scrollState = rememberLazyListState()
val fontSize = 14.sp val fontSize = 14.sp
val lineHeight = fontSize.toDp() * 1.5f val lineHeight = fontSize.toDp() * 1.5f
LazyColumnFor( LazyColumn(
model.items,
modifier = Modifier.fillMaxSize().withoutWidthConstraints(), modifier = Modifier.fillMaxSize().withoutWidthConstraints(),
state = scrollState, state = scrollState
itemContent = { FileTreeItemView(fontSize, lineHeight, it) } ) {
) items(model.items.size) {
FileTreeItemView(fontSize, lineHeight, model.items[it])
}
}
VerticalScrollbar( VerticalScrollbar(
Modifier.align(Alignment.CenterEnd), Modifier.align(Alignment.CenterEnd),
@ -83,7 +85,7 @@ private fun FileTreeItemView(fontSize: TextUnit, height: Dp, model: FileTree.Ite
FileItemIcon(Modifier.align(Alignment.CenterVertically), model) FileItemIcon(Modifier.align(Alignment.CenterVertically), model)
Text( Text(
text = model.name, text = model.name,
color = if (active.value) AmbientContentColor.current.copy(alpha = 0.60f) else AmbientContentColor.current, color = if (active.value) LocalContentColor.current.copy(alpha = 0.60f) else LocalContentColor.current,
modifier = Modifier modifier = Modifier
.align(Alignment.CenterVertically) .align(Alignment.CenterVertically)
.clipToBounds() .clipToBounds()
@ -110,10 +112,10 @@ private fun FileItemIcon(modifier: Modifier, model: FileTree.Item) = Box(modifie
is FileTree.ItemType.Folder -> when { is FileTree.ItemType.Folder -> when {
!type.canExpand -> Unit !type.canExpand -> Unit
type.isExpanded -> Icon( type.isExpanded -> Icon(
Icons.Default.KeyboardArrowDown, contentDescription = null, tint = AmbientContentColor.current Icons.Default.KeyboardArrowDown, contentDescription = null, tint = LocalContentColor.current
) )
else -> Icon( else -> Icon(
Icons.Default.KeyboardArrowRight, contentDescription = null, tint = AmbientContentColor.current Icons.Default.KeyboardArrowRight, contentDescription = null, tint = LocalContentColor.current
) )
} }
is FileTree.ItemType.File -> when (type.ext) { is FileTree.ItemType.File -> when (type.ext) {

10
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/statusbar/StatusBar.kt

@ -1,14 +1,14 @@
package org.jetbrains.codeviewer.ui.statusbar package org.jetbrains.codeviewer.ui.statusbar
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.AmbientContentColor import androidx.compose.material.LocalContentColor
import androidx.compose.material.Slider import androidx.compose.material.Slider
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.AmbientDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.*
import org.jetbrains.codeviewer.ui.common.Settings import org.jetbrains.codeviewer.ui.common.Settings
@ -26,13 +26,13 @@ fun StatusBar(settings: Settings) = Box(
Text( Text(
text = "Text size", text = "Text size",
modifier = Modifier.align(Alignment.CenterVertically), modifier = Modifier.align(Alignment.CenterVertically),
color = AmbientContentColor.current.copy(alpha = 0.60f), color = LocalContentColor.current.copy(alpha = 0.60f),
fontSize = 12.sp fontSize = 12.sp
) )
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(8.dp))
Providers(AmbientDensity provides AmbientDensity.current.scale(0.5f)) { CompositionLocalProvider(LocalDensity provides LocalDensity.current.scale(0.5f)) {
Slider( Slider(
(settings.fontSize - MinFontSize) / (MaxFontSize - MinFontSize), (settings.fontSize - MinFontSize) / (MaxFontSize - MinFontSize),
onValueChange = { settings.fontSize = lerp(MinFontSize, MaxFontSize, it) }, onValueChange = { settings.fontSize = lerp(MinFontSize, MaxFontSize, it) },

33
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/LazyColumnFor.kt

@ -1,33 +0,0 @@
package org.jetbrains.codeviewer.util
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyColumnForIndexed
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun LazyColumnFor(
size: Int,
modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
itemContent: @Composable LazyItemScope.(index: Int) -> Unit
) = LazyColumnForIndexed(
items = UnitList(size),
modifier = modifier,
state = state,
contentPadding = contentPadding,
horizontalAlignment = horizontalAlignment,
) { index, _ ->
itemContent(index)
}
private class UnitList(override val size: Int) : AbstractList<Unit>() {
override fun get(index: Int) = Unit
}

19
examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/util/VerticalSplittable.kt

@ -1,7 +1,9 @@
package org.jetbrains.codeviewer.util package org.jetbrains.codeviewer.util
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
@ -10,9 +12,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.gesture.scrollorientationlocking.Orientation
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -28,7 +30,7 @@ fun VerticalSplittable(
) = Layout({ ) = Layout({
children() children()
VerticalSplitter(splitterState, onResize) VerticalSplitter(splitterState, onResize)
}, modifier, measureBlock = { measurables, constraints -> }, modifier, measurePolicy = { measurables, constraints ->
require(measurables.size == 3) require(measurables.size == 3)
val firstPlaceable = measurables[0].measure(constraints.copy(minWidth = 0)) val firstPlaceable = measurables[0].measure(constraints.copy(minWidth = 0))
@ -60,6 +62,7 @@ fun VerticalSplitter(
onResize: (delta: Dp) -> Unit, onResize: (delta: Dp) -> Unit,
color: Color = AppTheme.colors.backgroundDark color: Color = AppTheme.colors.backgroundDark
) = Box { ) = Box {
val density = LocalDensity.current
Box( Box(
Modifier Modifier
.width(8.dp) .width(8.dp)
@ -67,14 +70,16 @@ fun VerticalSplitter(
.run { .run {
if (splitterState.isResizeEnabled) { if (splitterState.isResizeEnabled) {
this.draggable( this.draggable(
Orientation.Horizontal, state = rememberDraggableState {
with(density) {
onResize(it.toDp())
}
},
orientation = Orientation.Horizontal,
startDragImmediately = true, startDragImmediately = true,
onDragStarted = { splitterState.isResizing = true }, onDragStarted = { splitterState.isResizing = true },
onDragStopped = { splitterState.isResizing = false } onDragStopped = { splitterState.isResizing = false }
) { ).cursorForHorizontalResize()
onResize(it.toDp())
}
.cursorForHorizontalResize()
} else { } else {
this this
} }

6
examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Mouse.kt

@ -1,6 +1,6 @@
package org.jetbrains.codeviewer.platform package org.jetbrains.codeviewer.platform
import androidx.compose.desktop.AppWindowAmbient import androidx.compose.desktop.LocalAppWindow
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -21,9 +21,9 @@ actual fun Modifier.cursorForHorizontalResize(): Modifier = composed {
var isHover by remember { mutableStateOf(false) } var isHover by remember { mutableStateOf(false) }
if (isHover) { if (isHover) {
AppWindowAmbient.current!!.window.cursor = Cursor(Cursor.E_RESIZE_CURSOR) LocalAppWindow.current.window.cursor = Cursor(Cursor.E_RESIZE_CURSOR)
} else { } else {
AppWindowAmbient.current!!.window.cursor = Cursor.getDefaultCursor() LocalAppWindow.current.window.cursor = Cursor.getDefaultCursor()
} }
pointerMoveFilter( pointerMoveFilter(

15
examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Resources.kt

@ -1,24 +1,9 @@
package org.jetbrains.codeviewer.platform package org.jetbrains.codeviewer.platform
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.skija.Image
import java.io.InputStream
import java.net.URL
@Composable
actual fun imageResource(res: String) = androidx.compose.ui.res.imageResource("drawable/$res.png")
actual suspend fun imageFromUrl(url: String): ImageBitmap = withContext(Dispatchers.IO) {
val bytes = URL(url).openStream().buffered().use(InputStream::readBytes)
Image.makeFromEncoded(bytes).asImageBitmap()
}
@Composable @Composable
actual fun Font(name: String, res: String, weight: FontWeight, style: FontStyle): Font = actual fun Font(name: String, res: String, weight: FontWeight, style: FontStyle): Font =

9
examples/codeviewer/common/src/desktopMain/kotlin/org/jetbrains/codeviewer/platform/Selection.kt

@ -1,9 +0,0 @@
package org.jetbrains.codeviewer.platform
import androidx.compose.foundation.text.selection.DesktopSelectionContainer
import androidx.compose.runtime.Composable
@Composable
actual fun SelectionContainer(children: @Composable () -> Unit) {
DesktopSelectionContainer(content = children)
}

11
examples/codeviewer/desktop/src/jvmMain/kotlin/org/jetbrains/codeviewer/main.kt

@ -1,25 +1,18 @@
package org.jetbrains.codeviewer package org.jetbrains.codeviewer
import androidx.compose.desktop.Window import androidx.compose.desktop.Window
import androidx.compose.foundation.layout.ExperimentalLayout
import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.IntSize
import org.jetbrains.codeviewer.ui.MainView import org.jetbrains.codeviewer.ui.MainView
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import javax.imageio.ImageIO import javax.imageio.ImageIO
import javax.swing.SwingUtilities.invokeLater
@OptIn(ExperimentalLayout::class) fun main() = Window(
fun main() {
invokeLater {
Window(
title = "Code Viewer", title = "Code Viewer",
size = IntSize(1280, 768), size = IntSize(1280, 768),
icon = loadImageResource("ic_launcher.png") icon = loadImageResource("ic_launcher.png"),
) { ) {
MainView() MainView()
} }
}
}
@Suppress("SameParameterValue") @Suppress("SameParameterValue")

Loading…
Cancel
Save