From 7aaa8ff53215095f88585e53008b1a201f604e4d Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Tue, 8 Mar 2022 03:15:14 +0100 Subject: [PATCH 01/62] basic pan and zoom is working poc for highlighting using AnnotatedString --- app/build.gradle | 20 ++++ app/src/main/AndroidManifest.xml | 9 +- .../kodeeditor/ComposeMainActivity.kt | 59 ++++++++++ .../markusressel/kodeeditor/ui/theme/Color.kt | 8 ++ .../markusressel/kodeeditor/ui/theme/Shape.kt | 11 ++ .../markusressel/kodeeditor/ui/theme/Theme.kt | 44 ++++++++ .../markusressel/kodeeditor/ui/theme/Type.kt | 28 +++++ app/src/main/res/values/themes.xml | 5 + build.gradle | 3 +- library/build.gradle | 12 ++ .../library/AnnotatedStringHighlighter.kt | 33 ++++++ .../kodeeditor/library/KodeEditor.kt | 104 ++++++++++++++++++ 12 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt create mode 100644 app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt create mode 100644 app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt create mode 100644 app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt create mode 100644 app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt create mode 100644 app/src/main/res/values/themes.xml create mode 100644 library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt create mode 100644 library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt diff --git a/app/build.gradle b/app/build.gradle index 574053a..e68b292 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,6 +17,9 @@ android { setProperty("archivesBaseName", "KodeEditor_v${versionName}_(${versionCode})") multiDexEnabled true + vectorDrawables { + useSupportLibrary true + } } buildTypes { @@ -28,6 +31,7 @@ android { buildFeatures { viewBinding true + compose true } compileOptions { @@ -42,6 +46,15 @@ android { exclude 'META-INF/ASL2.0' exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } + } + kotlinOptions { + jvmTarget = '1.8' + } + composeOptions { + kotlinCompilerExtensionVersion compose_version } } @@ -55,6 +68,13 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' + implementation "androidx.compose.ui:ui:$compose_version" + implementation "androidx.compose.material:material:$compose_version" + implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' + implementation 'androidx.activity:activity-compose:1.3.1' + androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" + debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" def fuelVersion = "2.3.1" implementation "com.github.kittinunf.fuel:fuel:$fuelVersion" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f20dd8d..a5241f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,14 +13,19 @@ android:theme="@style/AppTheme" android:windowSoftInputMode="adjustResize"> + android:name=".ComposeMainActivity" + android:exported="true" + android:theme="@style/AppTheme"> + + \ No newline at end of file diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt new file mode 100644 index 0000000..3dcfcfd --- /dev/null +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -0,0 +1,59 @@ +package de.markusressel.kodeeditor + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.annotation.RawRes +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import de.markusressel.kodeeditor.library.KodeEditor +import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme +import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook + +class ComposeMainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + KodeEditorTheme { + // A surface container using the 'background' color from the theme + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + + val sampleText = readResourceFileAsText(R.raw.sample_text) + KodeEditor( + languageRuleBook = MarkdownRuleBook(), + initialText = sampleText + ) + } + } + } + } + + private fun readResourceFileAsText(@RawRes resourceId: Int): String { + return resources.openRawResource(resourceId).bufferedReader().readText() + } + +} + + +@Preview(showBackground = true) +@Composable +fun DefaultPreview() { + KodeEditorTheme { + KodeEditor( + languageRuleBook = MarkdownRuleBook(), + initialText = """ + # Heading + + Heading Test + + ## Subheading + + Subheading Text + """.trimIndent() + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt new file mode 100644 index 0000000..09ce275 --- /dev/null +++ b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt @@ -0,0 +1,8 @@ +package de.markusressel.kodeeditor.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple200 = Color(0xFFBB86FC) +val Purple500 = Color(0xFF6200EE) +val Purple700 = Color(0xFF3700B3) +val Teal200 = Color(0xFF03DAC5) \ No newline at end of file diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt new file mode 100644 index 0000000..90951f8 --- /dev/null +++ b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt @@ -0,0 +1,11 @@ +package de.markusressel.kodeeditor.ui.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) +) \ No newline at end of file diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt new file mode 100644 index 0000000..70e5bad --- /dev/null +++ b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt @@ -0,0 +1,44 @@ +package de.markusressel.kodeeditor.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material.MaterialTheme +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.runtime.Composable + +private val DarkColorPalette = darkColors( + primary = Purple200, + primaryVariant = Purple700, + secondary = Teal200 +) + +private val LightColorPalette = lightColors( + primary = Purple500, + primaryVariant = Purple700, + secondary = Teal200 + + /* Other default colors to override + background = Color.White, + surface = Color.White, + onPrimary = Color.White, + onSecondary = Color.Black, + onBackground = Color.Black, + onSurface = Color.Black, + */ +) + +@Composable +fun KodeEditorTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { + val colors = if (darkTheme) { + DarkColorPalette + } else { + LightColorPalette + } + + MaterialTheme( + colors = colors, + typography = Typography, + shapes = Shapes, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt new file mode 100644 index 0000000..0384128 --- /dev/null +++ b/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt @@ -0,0 +1,28 @@ +package de.markusressel.kodeeditor.ui.theme + +import androidx.compose.material.Typography +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 + +// Set of Material typography styles to start with +val Typography = Typography( + body1 = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp + ) + /* Other default text styles to override + button = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.W500, + fontSize = 14.sp + ), + caption = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 12.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..78554f9 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5eb2c36..d2b01ac 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { gradle_plugin_version = '7.0.4' - minSdkVersion = 19 + minSdkVersion = 21 versionName = "4.0.1" versionCode = 1 @@ -28,6 +28,7 @@ buildscript { flowBindingVersion = "1.0.0" timberKtVersion = "1.5.1" + compose_version = '1.1.1' } repositories { diff --git a/library/build.gradle b/library/build.gradle index b3b065c..5d21536 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -24,6 +24,14 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion compose_version + } } dependencies { @@ -33,6 +41,10 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.annotation:annotation:1.3.0' + implementation "androidx.compose.ui:ui:$compose_version" + implementation "androidx.compose.material:material:$compose_version" + implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + // RxFlow implementation "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBindingVersion" diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt b/library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt new file mode 100644 index 0000000..08a3410 --- /dev/null +++ b/library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt @@ -0,0 +1,33 @@ +package de.markusressel.kodeeditor.library + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import de.markusressel.kodehighlighter.core.LanguageRuleBook +import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme + +open class AnnotatedStringHighlighter( + private val languageRuleBook: LanguageRuleBook, + private val colorScheme: ColorScheme = languageRuleBook.defaultColorScheme +) : LanguageRuleBook by languageRuleBook { + + suspend fun highlight(text: String): AnnotatedString { + val ruleMatches = createHighlighting(text) + + val styles: List> = ruleMatches.map { (rule, matches) -> + matches.map { (start, end) -> + colorScheme.getStyles(rule).map { + // TODO: just for testing + SpanStyle( + color = Color.Green + ) + }.map { + AnnotatedString.Range(it, start = start, end = end) + } + }.flatten() + }.flatten() + + return AnnotatedString(text, spanStyles = styles) + } + +} \ No newline at end of file diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt new file mode 100644 index 0000000..5243f9d --- /dev/null +++ b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt @@ -0,0 +1,104 @@ +package de.markusressel.kodeeditor.library + +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTransformGestures +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material.Scaffold +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.TransformOrigin +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.input.OffsetMapping +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.input.TransformedText +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.unit.dp +import de.markusressel.kodehighlighter.core.LanguageRuleBook +import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme +import kotlinx.coroutines.runBlocking + +@Composable +fun KodeEditor( + modifier: Modifier = Modifier, + initialText: String = "", + languageRuleBook: LanguageRuleBook, + colorScheme: ColorScheme = languageRuleBook.defaultColorScheme +) { + val configuration = LocalConfiguration.current + + var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue(initialText)) + } + + var offset by remember { mutableStateOf(Offset.Zero) } + var zoom by remember { mutableStateOf(1f) } + + val visualTransformation = HighlightingTransformation(languageRuleBook, colorScheme) + + Scaffold(modifier = Modifier.background(Color.Black), backgroundColor = Color.Black) { + + BasicTextField( + modifier = Modifier + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + .background(Color.White) + .pointerInput(Unit) { + detectTransformGestures { centroid, pan, gestureZoom, gestureRotate -> + + val oldScale = zoom + val newScale = zoom * gestureZoom + + // For natural zooming and rotating, the centroid of the gesture should + // be the fixed point where zooming and rotating occurs. + // We compute where the centroid was (in the pre-transformed coordinate + // space), and then compute where it will be after this delta. + // We then compute what the new offset should be to keep the centroid + // visually stationary for rotating and zooming, and also apply the pan. + offset = (offset + centroid / oldScale) - (centroid / newScale + pan / oldScale) + + offset = Offset( + x = offset.x.coerceIn(0f, (size.width.toFloat() - (configuration.screenWidthDp.dp.toPx() / newScale)).coerceAtLeast(0f)), + y = offset.y.coerceIn(0f, (size.height.toFloat() - (configuration.screenHeightDp.dp.toPx() / newScale)).coerceAtLeast(0f)), + ) + + zoom = (newScale).coerceIn(0.1f, 5f) + } + } + .graphicsLayer( + transformOrigin = TransformOrigin(0f, 0f), + scaleX = zoom, scaleY = zoom, + translationX = -offset.x * zoom, + translationY = -offset.y * zoom, + ), + value = text, + onValueChange = { text = it }, + visualTransformation = visualTransformation, + ) + } +} + +class HighlightingTransformation( + ruleBook: LanguageRuleBook, + colorScheme: ColorScheme +) : VisualTransformation { + + private val highlighter = AnnotatedStringHighlighter(ruleBook, colorScheme) + + override fun filter(text: AnnotatedString): TransformedText { + // TODO: run asynchronously + val highlightedText = runBlocking { + highlighter.highlight(text.text) + } + return TransformedText(highlightedText, OffsetMapping.Identity) + } +} From dd709c4b390beaec054202d312cb1fb59d96cb71 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 4 Apr 2022 22:02:22 +0200 Subject: [PATCH 02/62] update dependencies --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e68b292..bb9a380 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -71,8 +71,8 @@ dependencies { implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' - implementation 'androidx.activity:activity-compose:1.3.1' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1' + implementation 'androidx.activity:activity-compose:1.4.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" From db073399a6163e86e79cd40d29bea88b5f2e3cab Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 3 Oct 2022 02:11:23 +0200 Subject: [PATCH 03/62] update dependencies --- app/build.gradle | 12 ++++-------- app/src/main/AndroidManifest.xml | 3 +-- .../markusressel/kodeeditor/ComposeMainActivity.kt | 11 +++++------ build.gradle | 8 ++++---- gradle/wrapper/gradle-wrapper.properties | 2 +- library/build.gradle | 5 +++-- library/src/main/AndroidManifest.xml | 2 +- .../de/markusressel/kodeeditor/library/KodeEditor.kt | 8 ++++++-- 8 files changed, 25 insertions(+), 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index bb9a380..f56b05f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,14 +40,9 @@ android { } packagingOptions { - pickFirst 'META-INF/proguard/androidx-annotations.pro' - exclude 'LICENSE.txt' - exclude 'META-INF/DEPENDENCIES' - exclude 'META-INF/ASL2.0' - exclude 'META-INF/NOTICE' - exclude 'META-INF/LICENSE' resources { - excludes += '/META-INF/{AL2.0,LGPL2.1}' + excludes += ['/META-INF/{AL2.0,LGPL2.1}', 'LICENSE.txt', 'META-INF/DEPENDENCIES', 'META-INF/ASL2.0', 'META-INF/NOTICE', 'META-INF/LICENSE'] + pickFirsts += ['META-INF/proguard/androidx-annotations.pro'] } } kotlinOptions { @@ -56,6 +51,7 @@ android { composeOptions { kotlinCompilerExtensionVersion compose_version } + namespace 'de.markusressel.kodeeditor' } dependencies { @@ -67,7 +63,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.4.1' - implementation 'com.google.android.material:material:1.5.0' + implementation 'com.google.android.material:material:1.6.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a5241f9..b4a90b2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 3dcfcfd..29889f9 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -19,9 +19,10 @@ class ComposeMainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContent { KodeEditorTheme { - // A surface container using the 'background' color from the theme - Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { - + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colors.background + ) { val sampleText = readResourceFileAsText(R.raw.sample_text) KodeEditor( languageRuleBook = MarkdownRuleBook(), @@ -32,9 +33,7 @@ class ComposeMainActivity : ComponentActivity() { } } - private fun readResourceFileAsText(@RawRes resourceId: Int): String { - return resources.openRawResource(resourceId).bufferedReader().readText() - } + private fun readResourceFileAsText(@RawRes resourceId: Int) = resources.openRawResource(resourceId).bufferedReader().readText() } diff --git a/build.gradle b/build.gradle index d2b01ac..8f84d35 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.6.10' - ext.dokka_version = '1.6.10' + ext.kotlin_version = '1.6.21' + ext.dokka_version = '1.6.21' ext { group = 'com.github.markusressel' - gradle_plugin_version = '7.0.4' + gradle_plugin_version = '7.2.0' minSdkVersion = 21 versionName = "4.0.1" @@ -28,7 +28,7 @@ buildscript { flowBindingVersion = "1.0.0" timberKtVersion = "1.5.1" - compose_version = '1.1.1' + compose_version = '1.2.0-beta02' } repositories { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 49ca654..8bb77df 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip diff --git a/library/build.gradle b/library/build.gradle index 5d21536..4b41a73 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -32,6 +32,7 @@ android { composeOptions { kotlinCompilerExtensionVersion compose_version } + namespace 'de.markusressel.kodeeditor.library' } dependencies { @@ -55,8 +56,8 @@ dependencies { // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1" // Zoom Layout Container api 'com.otaliastudios:zoomlayout:1.9.0' diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index 692fb76..cc947c5 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -1 +1 @@ - + diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt index 5243f9d..4826f1b 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt @@ -2,6 +2,7 @@ package de.markusressel.kodeeditor.library import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTransformGestures +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Scaffold @@ -43,10 +44,13 @@ fun KodeEditor( val visualTransformation = HighlightingTransformation(languageRuleBook, colorScheme) - Scaffold(modifier = Modifier.background(Color.Black), backgroundColor = Color.Black) { - + Scaffold( + modifier = Modifier.background(Color.Black), + backgroundColor = Color.Black + ) { contentPadding -> BasicTextField( modifier = Modifier + .padding(contentPadding) .wrapContentSize( align = Alignment.TopStart, unbounded = true From 8cd94141dee68dacedcd8cc0e755769bc08fdc79 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 3 Oct 2022 02:20:51 +0200 Subject: [PATCH 04/62] update dependencies --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- library/build.gradle | 13 ++++++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 8f84d35..73870eb 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.6.21' + ext.kotlin_version = '1.7.10' ext.dokka_version = '1.6.21' ext { group = 'com.github.markusressel' - gradle_plugin_version = '7.2.0' + gradle_plugin_version = '7.3.0' minSdkVersion = 21 versionName = "4.0.1" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8bb77df..e9bf75f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip diff --git a/library/build.gradle b/library/build.gradle index 4b41a73..382a053 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -39,19 +39,18 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" // api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' - implementation 'androidx.appcompat:appcompat:1.4.1' - implementation 'androidx.annotation:annotation:1.3.0' + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'androidx.annotation:annotation:1.5.0' - implementation "androidx.compose.ui:ui:$compose_version" - implementation "androidx.compose.material:material:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation "androidx.compose.ui:ui:1.2.1" + implementation "androidx.compose.material:material:1.2.1" + implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" // RxFlow implementation "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBindingVersion" // Lifecycle - def lifecycle_version = "2.4.1" - implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1" // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") From d5a0dee278dfa396697bd8d23fd7354a9048280a Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 3 Oct 2022 02:24:29 +0200 Subject: [PATCH 05/62] update dependencies --- app/build.gradle | 10 +++++----- build.gradle | 7 ++++--- library/build.gradle | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f56b05f..bf81f07 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -49,7 +49,7 @@ android { jvmTarget = '1.8' } composeOptions { - kotlinCompilerExtensionVersion compose_version + kotlinCompilerExtensionVersion compose_compiler_version } namespace 'de.markusressel.kodeeditor' } @@ -62,13 +62,13 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.4.1' - implementation 'com.google.android.material:material:1.6.0' + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'com.google.android.material:material:1.6.1' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1' - implementation 'androidx.activity:activity-compose:1.4.0' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' + implementation 'androidx.activity:activity-compose:1.6.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" diff --git a/build.gradle b/build.gradle index 73870eb..3ed3406 100644 --- a/build.gradle +++ b/build.gradle @@ -13,8 +13,8 @@ buildscript { versionName = "4.0.1" versionCode = 1 - compileSdkVersion = 31 - targetSdkVersion = 31 + compileSdkVersion = 33 + targetSdkVersion = 33 buildToolsVersion = "30.0.3" // DEPENDENCIES @@ -28,7 +28,8 @@ buildscript { flowBindingVersion = "1.0.0" timberKtVersion = "1.5.1" - compose_version = '1.2.0-beta02' + compose_compiler_version = '1.3.1' + compose_version = '1.3.0-beta03' } repositories { diff --git a/library/build.gradle b/library/build.gradle index 382a053..27b54b4 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -30,7 +30,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion compose_version + kotlinCompilerExtensionVersion compose_compiler_version } namespace 'de.markusressel.kodeeditor.library' } From cb43f42c6c6895fb529d7e87eafbe4b2b02438f2 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 3 Oct 2022 02:58:17 +0200 Subject: [PATCH 06/62] refactored ZoomLayout --- .../kodeeditor/library/KodeEditor.kt | 64 +++---------- .../kodeeditor/library/ZoomLayout.kt | 93 +++++++++++++++++++ 2 files changed, 108 insertions(+), 49 deletions(-) create mode 100644 library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt index 4826f1b..26b7972 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt @@ -1,27 +1,23 @@ package de.markusressel.kodeeditor.library import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.detectTransformGestures import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Scaffold -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.TransformOrigin -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.input.OffsetMapping import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TransformedText import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.unit.dp import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import kotlinx.coroutines.runBlocking @@ -33,61 +29,31 @@ fun KodeEditor( languageRuleBook: LanguageRuleBook, colorScheme: ColorScheme = languageRuleBook.defaultColorScheme ) { - val configuration = LocalConfiguration.current - var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue(initialText)) } - var offset by remember { mutableStateOf(Offset.Zero) } - var zoom by remember { mutableStateOf(1f) } - val visualTransformation = HighlightingTransformation(languageRuleBook, colorScheme) Scaffold( modifier = Modifier.background(Color.Black), backgroundColor = Color.Black ) { contentPadding -> - BasicTextField( - modifier = Modifier - .padding(contentPadding) - .wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ) - .background(Color.White) - .pointerInput(Unit) { - detectTransformGestures { centroid, pan, gestureZoom, gestureRotate -> - - val oldScale = zoom - val newScale = zoom * gestureZoom - // For natural zooming and rotating, the centroid of the gesture should - // be the fixed point where zooming and rotating occurs. - // We compute where the centroid was (in the pre-transformed coordinate - // space), and then compute where it will be after this delta. - // We then compute what the new offset should be to keep the centroid - // visually stationary for rotating and zooming, and also apply the pan. - offset = (offset + centroid / oldScale) - (centroid / newScale + pan / oldScale) - - offset = Offset( - x = offset.x.coerceIn(0f, (size.width.toFloat() - (configuration.screenWidthDp.dp.toPx() / newScale)).coerceAtLeast(0f)), - y = offset.y.coerceIn(0f, (size.height.toFloat() - (configuration.screenHeightDp.dp.toPx() / newScale)).coerceAtLeast(0f)), - ) - - zoom = (newScale).coerceIn(0.1f, 5f) - } - } - .graphicsLayer( - transformOrigin = TransformOrigin(0f, 0f), - scaleX = zoom, scaleY = zoom, - translationX = -offset.x * zoom, - translationY = -offset.y * zoom, - ), + ZoomLayout { + BasicTextField( + modifier = Modifier + .padding(contentPadding) + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + .background(Color.White), value = text, onValueChange = { text = it }, visualTransformation = visualTransformation, - ) + ) + } } } diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt new file mode 100644 index 0000000..ff77a49 --- /dev/null +++ b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt @@ -0,0 +1,93 @@ +package de.markusressel.kodeeditor.library + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTransformGestures +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.TransformOrigin +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Preview +@Composable +fun ZoomLayoutPreview() { + ZoomLayout( + modifier = Modifier + .padding(16.dp) + .background(Color.White) + ) { + Image( + modifier = Modifier.size(1000.dp), + painter = painterResource(id = android.R.drawable.zoom_plate), + contentDescription = "", + ) + } +} + +@Composable +fun ZoomLayout( + modifier: Modifier = Modifier, + content: @Composable () -> Unit, +) { + Box(modifier = modifier.wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + ) { + val configuration = LocalConfiguration.current + + var offset by remember { mutableStateOf(Offset.Zero) } + var zoom by remember { mutableStateOf(1f) } + + Box( + modifier = Modifier + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + .background(Color.White) + .pointerInput(Unit) { + detectTransformGestures { centroid, pan, gestureZoom, gestureRotate -> + + val oldScale = zoom + val newScale = zoom * gestureZoom + + // For natural zooming and rotating, the centroid of the gesture should + // be the fixed point where zooming and rotating occurs. + // We compute where the centroid was (in the pre-transformed coordinate + // space), and then compute where it will be after this delta. + // We then compute what the new offset should be to keep the centroid + // visually stationary for rotating and zooming, and also apply the pan. + offset = (offset + centroid / oldScale) - (centroid / newScale + pan / oldScale) + + offset = Offset( + x = offset.x.coerceIn(0f, (size.width.toFloat() - (configuration.screenWidthDp.dp.toPx() / newScale)).coerceAtLeast(0f)), + y = offset.y.coerceIn(0f, (size.height.toFloat() - (configuration.screenHeightDp.dp.toPx() / newScale)).coerceAtLeast(0f)), + ) + + zoom = (newScale).coerceIn(0.1f, 5f) + } + } + .graphicsLayer( + transformOrigin = TransformOrigin(0f, 0f), + scaleX = zoom, scaleY = zoom, + translationX = -offset.x * zoom, + translationY = -offset.y * zoom, + ), + ) { + content() + } + } +} \ No newline at end of file From 9b157c0d7934ddd8648fbb6411a434dbc1fd4023 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 3 Oct 2022 03:18:13 +0200 Subject: [PATCH 07/62] ZoomLayout preview --- app/build.gradle | 1 + library/build.gradle | 7 +++- .../kodeeditor/library/ZoomLayout.kt | 37 +++++++++++-------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index bf81f07..8b8c758 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -71,6 +71,7 @@ dependencies { implementation 'androidx.activity:activity-compose:1.6.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" + implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" def fuelVersion = "2.3.1" implementation "com.github.kittinunf.fuel:fuel:$fuelVersion" diff --git a/library/build.gradle b/library/build.gradle index 27b54b4..a4d56ae 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -46,6 +46,9 @@ dependencies { implementation "androidx.compose.material:material:1.2.1" implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" + debugImplementation "androidx.compose.ui:ui-tooling:1.2.1" + implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" + // RxFlow implementation "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBindingVersion" @@ -55,8 +58,8 @@ dependencies { // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" // Zoom Layout Container api 'com.otaliastudios:zoomlayout:1.9.0' diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt index ff77a49..e91c9df 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt @@ -1,12 +1,9 @@ package de.markusressel.kodeeditor.library -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTransformGestures -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.layout.* +import androidx.compose.material.Surface import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -16,7 +13,6 @@ import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -28,11 +24,21 @@ fun ZoomLayoutPreview() { .padding(16.dp) .background(Color.White) ) { - Image( - modifier = Modifier.size(1000.dp), - painter = painterResource(id = android.R.drawable.zoom_plate), - contentDescription = "", - ) + Column(modifier = Modifier) { + for (i in 1..10) { + Row(modifier = Modifier) { + for (j in 1..10) { + val k = j + i % 2 + Surface( + modifier = Modifier.size(20.dp), color = when { + k % 2 == 0 -> Color.Black + else -> Color.White + }) { + } + } + } + } + } } } @@ -41,10 +47,11 @@ fun ZoomLayout( modifier: Modifier = Modifier, content: @Composable () -> Unit, ) { - Box(modifier = modifier.wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ) + Box( + modifier = modifier.wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) ) { val configuration = LocalConfiguration.current From 9397b93d4762a936194431f3151633f925ecdceb Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 3 Oct 2022 03:24:39 +0200 Subject: [PATCH 08/62] simpler code --- .../java/de/markusressel/kodeeditor/library/ZoomLayout.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt index e91c9df..a94fe57 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt @@ -28,10 +28,10 @@ fun ZoomLayoutPreview() { for (i in 1..10) { Row(modifier = Modifier) { for (j in 1..10) { - val k = j + i % 2 + val k = (i + j) % 2 Surface( - modifier = Modifier.size(20.dp), color = when { - k % 2 == 0 -> Color.Black + modifier = Modifier.size(20.dp), color = when (k) { + 1 -> Color.Black else -> Color.White }) { } From 91b9840417ec6a81927f0ed7e79966be3788f1a3 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 8 Oct 2022 23:47:16 +0200 Subject: [PATCH 09/62] upgraded KodeHighlighter dependency removed unnecessary AnnotatedStringHighlighter (its now part of the KodeHighlighter library) added colorScheme parameter to CodeEditorLayout (breaking change) --- .../kodeeditor/ComposeMainActivity.kt | 48 +++++++++---- .../markusressel/kodeeditor/MainActivity.kt | 2 + build.gradle | 4 +- .../library/AnnotatedStringHighlighter.kt | 33 --------- .../kodeeditor/library/KodeEditor.kt | 60 +++++----------- .../library/view/CodeEditorLayout.kt | 11 +++ .../kodeeditor/library/view/CodeEditorView.kt | 69 ++++++++++++++----- 7 files changed, 118 insertions(+), 109 deletions(-) delete mode 100644 library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 29889f9..b48b55c 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -8,11 +8,17 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import de.markusressel.kodeeditor.library.KodeEditor import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook +import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle class ComposeMainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -20,20 +26,27 @@ class ComposeMainActivity : ComponentActivity() { setContent { KodeEditorTheme { Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colors.background + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colors.background ) { - val sampleText = readResourceFileAsText(R.raw.sample_text) + var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { + val initialText = readResourceFileAsText(R.raw.sample_text) + mutableStateOf(TextFieldValue(initialText)) + } + KodeEditor( - languageRuleBook = MarkdownRuleBook(), - initialText = sampleText + languageRuleBook = MarkdownRuleBook(), + colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), + text = text, + onValueChange = { text = it } ) } } } } - private fun readResourceFileAsText(@RawRes resourceId: Int) = resources.openRawResource(resourceId).bufferedReader().readText() + private fun readResourceFileAsText(@RawRes resourceId: Int) = + resources.openRawResource(resourceId).bufferedReader().readText() } @@ -42,17 +55,24 @@ class ComposeMainActivity : ComponentActivity() { @Composable fun DefaultPreview() { KodeEditorTheme { - KodeEditor( - languageRuleBook = MarkdownRuleBook(), - initialText = """ - # Heading + var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { + val initialText = """ + # Heading - Heading Test + Heading Test - ## Subheading + ## Subheading - Subheading Text - """.trimIndent() + Subheading Text + """.trimIndent() + mutableStateOf(TextFieldValue(initialText)) + } + + KodeEditor( + languageRuleBook = MarkdownRuleBook(), + colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), + text = text, + onValueChange = { text = it } ) } } \ No newline at end of file diff --git a/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt index c09e580..0a8bc01 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt @@ -9,6 +9,7 @@ import com.github.kittinunf.fuel.Fuel import de.markusressel.kodeeditor.databinding.ActivityMainBinding import de.markusressel.kodeeditor.library.extensions.dpToPx import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook +import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorScheme class MainActivity : AppCompatActivity() { @@ -22,6 +23,7 @@ class MainActivity : AppCompatActivity() { binding.codeEditorLayout.apply { languageRuleBook = MarkdownRuleBook() + colorScheme = DarkBackgroundColorScheme() lineNumberGenerator = { lines -> (1..lines).map { " $it " } } diff --git a/build.gradle b/build.gradle index 3ed3406..9490345 100644 --- a/build.gradle +++ b/build.gradle @@ -19,8 +19,8 @@ buildscript { // DEPENDENCIES - kodeHighlighterVersion = "v3.0.0" -// kodeHighlighterVersion = "master-SNAPSHOT" +// kodeHighlighterVersion = "v3.0.0" + kodeHighlighterVersion = "master-SNAPSHOT" javaxAnnotationVersion = "10.0-b28" aboutlibrariesVersion = "8.2.0" diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt b/library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt deleted file mode 100644 index 08a3410..0000000 --- a/library/src/main/java/de/markusressel/kodeeditor/library/AnnotatedStringHighlighter.kt +++ /dev/null @@ -1,33 +0,0 @@ -package de.markusressel.kodeeditor.library - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import de.markusressel.kodehighlighter.core.LanguageRuleBook -import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme - -open class AnnotatedStringHighlighter( - private val languageRuleBook: LanguageRuleBook, - private val colorScheme: ColorScheme = languageRuleBook.defaultColorScheme -) : LanguageRuleBook by languageRuleBook { - - suspend fun highlight(text: String): AnnotatedString { - val ruleMatches = createHighlighting(text) - - val styles: List> = ruleMatches.map { (rule, matches) -> - matches.map { (start, end) -> - colorScheme.getStyles(rule).map { - // TODO: just for testing - SpanStyle( - color = Color.Green - ) - }.map { - AnnotatedString.Range(it, start = start, end = end) - } - }.flatten() - }.flatten() - - return AnnotatedString(text, spanStyles = styles) - } - -} \ No newline at end of file diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt index 26b7972..9272590 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt @@ -3,45 +3,36 @@ package de.markusressel.kodeeditor.library import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.input.OffsetMapping +import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.text.input.TransformedText -import androidx.compose.ui.text.input.VisualTransformation import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme -import kotlinx.coroutines.runBlocking +import de.markusressel.kodehighlighter.core.ui.KodeTextField +/** + * Compose version of the KodeEditorLayout + */ @Composable fun KodeEditor( - modifier: Modifier = Modifier, - initialText: String = "", - languageRuleBook: LanguageRuleBook, - colorScheme: ColorScheme = languageRuleBook.defaultColorScheme + modifier: Modifier = Modifier, + text: TextFieldValue, + languageRuleBook: LanguageRuleBook, + colorScheme: ColorScheme, + onValueChange: (TextFieldValue) -> Unit, ) { - var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { - mutableStateOf(TextFieldValue(initialText)) - } - - val visualTransformation = HighlightingTransformation(languageRuleBook, colorScheme) - Scaffold( - modifier = Modifier.background(Color.Black), - backgroundColor = Color.Black + modifier = Modifier + .background(Color.Black) + .then(modifier), + backgroundColor = Color.Black ) { contentPadding -> - ZoomLayout { - BasicTextField( + KodeTextField( modifier = Modifier .padding(contentPadding) .wrapContentSize( @@ -50,25 +41,10 @@ fun KodeEditor( ) .background(Color.White), value = text, - onValueChange = { text = it }, - visualTransformation = visualTransformation, + languageRuleBook = languageRuleBook, + colorScheme = colorScheme, + onValueChange = onValueChange, ) } } } - -class HighlightingTransformation( - ruleBook: LanguageRuleBook, - colorScheme: ColorScheme -) : VisualTransformation { - - private val highlighter = AnnotatedStringHighlighter(ruleBook, colorScheme) - - override fun filter(text: AnnotatedString): TransformedText { - // TODO: run asynchronously - val highlightedText = runBlocking { - highlighter.highlight(text.text) - } - return TransformedText(highlightedText, OffsetMapping.Identity) - } -} diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorLayout.kt index e37efd4..1a02580 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorLayout.kt @@ -8,6 +8,7 @@ import android.graphics.Rect import android.graphics.drawable.GradientDrawable import android.os.Build import android.text.Layout +import android.text.style.CharacterStyle import android.util.AttributeSet import android.util.Log import android.util.TypedValue @@ -22,6 +23,7 @@ import de.markusressel.kodeeditor.library.extensions.createSnapshot import de.markusressel.kodeeditor.library.extensions.dpToPx import de.markusressel.kodeeditor.library.extensions.getColor import de.markusressel.kodehighlighter.core.LanguageRuleBook +import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -122,6 +124,15 @@ constructor( codeEditorView.languageRuleBook = value } + /** + * The currently active syntax highlighter (if any) + */ + var colorScheme: ColorScheme? + get() = codeEditorView.colorScheme + set(value) { + codeEditorView.colorScheme = value + } + /** * Set the text in the editor * diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorView.kt b/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorView.kt index 98e83cd..e21ab83 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorView.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/view/CodeEditorView.kt @@ -2,6 +2,7 @@ package de.markusressel.kodeeditor.library.view import android.content.Context import android.graphics.Color +import android.text.style.CharacterStyle import android.util.AttributeSet import android.view.LayoutInflater import android.view.View @@ -14,6 +15,7 @@ import de.markusressel.kodeeditor.library.R import de.markusressel.kodeeditor.library.extensions.getColor import de.markusressel.kodeeditor.library.extensions.setViewBackgroundWithoutResettingPadding import de.markusressel.kodehighlighter.core.LanguageRuleBook +import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import de.markusressel.kodehighlighter.core.util.EditTextHighlighter import de.markusressel.kodehighlighter.core.util.StatefulSpannableHighlighter @@ -21,8 +23,8 @@ import de.markusressel.kodehighlighter.core.util.StatefulSpannableHighlighter * Code Editor that allows pinch-to-zoom */ open class CodeEditorView -@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) - : ZoomLayout(context, attrs, defStyleAttr), SelectionChangedListener { +@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + ZoomLayout(context, attrs, defStyleAttr), SelectionChangedListener { /** * The actual text editor content @@ -37,18 +39,43 @@ open class CodeEditorView /** * The currently active syntax highlighter (if any) */ - var languageRuleBook: LanguageRuleBook? - get() = codeEditText.highlighter?.languageRuleBook + var languageRuleBook: LanguageRuleBook? = null + //get() = codeEditText.highlighter?.languageRuleBook set(value) { - if (value != null) { - codeEditText.highlighter = EditTextHighlighter(codeEditText, value) - codeTextView.highlighter = StatefulSpannableHighlighter(value, value.defaultColorScheme) - } else { - codeEditText.highlighter = null - codeTextView.highlighter = null - } + field = value + updateHighlighter(value, colorScheme) } + /** + * The color scheme to use for the currently active syntax highlighter (if any) + */ + var colorScheme: ColorScheme? = null + //get() = codeEditText.highlighter?.colorScheme + set(value) { + field = value + updateHighlighter(languageRuleBook, value) + } + + private fun updateHighlighter( + languageRuleBook: LanguageRuleBook?, + colorScheme: ColorScheme?, + ) { + if (languageRuleBook != null && colorScheme != null) { + codeEditText.highlighter = EditTextHighlighter( + target = codeEditText, + languageRuleBook = languageRuleBook, + colorScheme = colorScheme + ) + codeTextView.highlighter = StatefulSpannableHighlighter( + languageRuleBook = languageRuleBook, + colorScheme = colorScheme + ) + } else { + codeEditText.highlighter = null + codeTextView.highlighter = null + } + } + /** * Listener for selection changes */ @@ -124,11 +151,15 @@ open class CodeEditorView private fun readParameters(attrs: AttributeSet?, defStyleAttr: Int) { val a = context.obtainStyledAttributes(attrs, R.styleable.CodeEditorView, defStyleAttr, 0) - val editTextBackgroundColor = a.getColor(context, - defaultColor = Color.WHITE, - styleableRes = R.styleable.CodeEditorView_ke_editor_backgroundColor, - attr = intArrayOf(R.attr.ke_editor_backgroundColor, - android.R.attr.windowBackground)) + val editTextBackgroundColor = a.getColor( + context, + defaultColor = Color.WHITE, + styleableRes = R.styleable.CodeEditorView_ke_editor_backgroundColor, + attr = intArrayOf( + R.attr.ke_editor_backgroundColor, + android.R.attr.windowBackground + ) + ) codeEditText.setBackgroundColor(editTextBackgroundColor) val maxRealZoom = a.getFloat(R.styleable.CodeEditorView_ke_editor_maxZoom, DEFAULT_MAX_ZOOM) @@ -173,8 +204,10 @@ open class CodeEditorView val containerHeight = height - (paddingTop + paddingBottom) val codeEditTextLayoutParams = (codeEditText.layoutParams as MarginLayoutParams) - val minimumWidth = containerWidth + (codeEditTextLayoutParams.leftMargin + codeEditTextLayoutParams.rightMargin) - val minimumHeight = containerHeight - (codeEditTextLayoutParams.topMargin + codeEditTextLayoutParams.bottomMargin) + val minimumWidth = + containerWidth + (codeEditTextLayoutParams.leftMargin + codeEditTextLayoutParams.rightMargin) + val minimumHeight = + containerHeight - (codeEditTextLayoutParams.topMargin + codeEditTextLayoutParams.bottomMargin) codeEditText.minWidth = minimumWidth codeTextView.minWidth = minimumWidth From 4f779dad795c9166e74c45663e1411e9511b427a Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 9 Oct 2022 01:08:49 +0200 Subject: [PATCH 10/62] fix jdk dependency --- app/build.gradle | 2 +- library/build.gradle | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8b8c758..a74ff8f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,7 +60,7 @@ dependencies { // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion") - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.6.1' diff --git a/library/build.gradle b/library/build.gradle index a4d56ae..69c2abc 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -36,7 +36,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' implementation 'androidx.appcompat:appcompat:1.5.1' @@ -56,7 +56,9 @@ dependencies { implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1" // Syntax Highlighting - api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") + api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") { + changing = true + } implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" From 2b4a425fd8c91ad86e49e0b8c87f55efeb04edf9 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 9 Oct 2022 02:20:26 +0200 Subject: [PATCH 11/62] color fixes --- .../kodeeditor/ComposeMainActivity.kt | 16 +++++--- .../kodeeditor/library/KodeEditor.kt | 41 ++++++++----------- .../kodeeditor/library/ZoomLayout.kt | 1 - 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index b48b55c..d496ee1 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -4,9 +4,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.RawRes -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface +import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -15,6 +13,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import de.markusressel.kodeeditor.library.KodeEditor import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook @@ -25,9 +24,11 @@ class ComposeMainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContent { KodeEditorTheme { - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colors.background + Box( + modifier = Modifier + .fillMaxSize() + .width(IntrinsicSize.Max) + .height(IntrinsicSize.Max), ) { var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { val initialText = readResourceFileAsText(R.raw.sample_text) @@ -35,6 +36,9 @@ class ComposeMainActivity : ComponentActivity() { } KodeEditor( + modifier = Modifier + .matchParentSize() + .padding(8.dp), languageRuleBook = MarkdownRuleBook(), colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), text = text, diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt index 9272590..065b8de 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt @@ -1,18 +1,16 @@ package de.markusressel.kodeeditor.library -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.input.TextFieldValue import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import de.markusressel.kodehighlighter.core.ui.KodeTextField +import de.markusressel.kodehighlighter.core.ui.KodeTextFieldColors +import de.markusressel.kodehighlighter.core.ui.KodeTextFieldDefaults /** * Compose version of the KodeEditorLayout @@ -24,27 +22,20 @@ fun KodeEditor( languageRuleBook: LanguageRuleBook, colorScheme: ColorScheme, onValueChange: (TextFieldValue) -> Unit, + colors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), ) { - Scaffold( - modifier = Modifier - .background(Color.Black) - .then(modifier), - backgroundColor = Color.Black - ) { contentPadding -> - ZoomLayout { - KodeTextField( - modifier = Modifier - .padding(contentPadding) - .wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ) - .background(Color.White), - value = text, - languageRuleBook = languageRuleBook, - colorScheme = colorScheme, - onValueChange = onValueChange, - ) - } + ZoomLayout(modifier = modifier) { + KodeTextField( + modifier = Modifier + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ), + value = text, + languageRuleBook = languageRuleBook, + colorScheme = colorScheme, + onValueChange = onValueChange, + colors = colors, + ) } } diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt index a94fe57..61860f1 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt @@ -64,7 +64,6 @@ fun ZoomLayout( align = Alignment.TopStart, unbounded = true ) - .background(Color.White) .pointerInput(Unit) { detectTransformGestures { centroid, pan, gestureZoom, gestureRotate -> From adbfb3c27c455768d1e428312ab3aa741d164117 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 9 Oct 2022 02:51:48 +0200 Subject: [PATCH 12/62] added LineNumbers --- .../kodeeditor/ComposeMainActivity.kt | 4 +- .../kodeeditor/library/KodeEditor.kt | 66 +++++++++++++++---- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index d496ee1..58dbda0 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import de.markusressel.kodeeditor.library.KodeEditor import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook @@ -37,8 +36,7 @@ class ComposeMainActivity : ComponentActivity() { KodeEditor( modifier = Modifier - .matchParentSize() - .padding(8.dp), + .matchParentSize(), languageRuleBook = MarkdownRuleBook(), colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), text = text, diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt index 065b8de..f6c629b 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt @@ -1,11 +1,17 @@ package de.markusressel.kodeeditor.library -import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import de.markusressel.kodehighlighter.core.ui.KodeTextField @@ -23,19 +29,53 @@ fun KodeEditor( colorScheme: ColorScheme, onValueChange: (TextFieldValue) -> Unit, colors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), + enabled: Boolean = true, ) { ZoomLayout(modifier = modifier) { - KodeTextField( - modifier = Modifier - .wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ), - value = text, - languageRuleBook = languageRuleBook, - colorScheme = colorScheme, - onValueChange = onValueChange, - colors = colors, - ) + Row( + modifier = Modifier.fillMaxSize(), + ) { + LineNumbers( + text = text.text, + colors = colors, + enabled = enabled, + ) + + KodeTextField( + modifier = Modifier + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + .padding(horizontal = 4.dp), + value = text, + languageRuleBook = languageRuleBook, + colorScheme = colorScheme, + onValueChange = onValueChange, + colors = colors, + ) + } + } +} + +@Composable +fun LineNumbers( + text: String, + colors: KodeTextFieldColors, + enabled: Boolean, +) { + val lineNumbers by produceState("") { + val lineCount = text.lines().size + value = (1..lineCount).joinToString(separator = "\n") } + + Text( + modifier = Modifier + .wrapContentWidth() + .background(color = colors.backgroundColor(enabled = enabled).value) + .padding(start = 4.dp, end = 4.dp), + text = lineNumbers, + textAlign = TextAlign.End, + ) } + From cca81ce6c14aab2a7d9b63c017444be392bd7d1e Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 9 Oct 2022 15:46:14 +0200 Subject: [PATCH 13/62] exported .editorconfig refactoring previews --- .editorconfig | 925 ++++++++++++++++++ .../kodeeditor/ComposeMainActivity.kt | 2 +- library/build.gradle | 2 + .../library/{ => compose}/KodeEditor.kt | 72 +- .../kodeeditor/library/compose/LineNumbers.kt | 51 + .../library/{ => compose}/ZoomLayout.kt | 2 +- 6 files changed, 1020 insertions(+), 34 deletions(-) create mode 100644 .editorconfig rename library/src/main/java/de/markusressel/kodeeditor/library/{ => compose}/KodeEditor.kt (55%) create mode 100644 library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt rename library/src/main/java/de/markusressel/kodeeditor/library/{ => compose}/ZoomLayout.kt (98%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0eb2079 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,925 @@ +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = false +max_line_length = 120 +tab_width = 4 +ij_continuation_indent_size = 4 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = false +ij_smart_tabs = false +ij_visual_guides = none +ij_wrap_on_typing = false + +[*.java] +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = false +ij_java_align_multiline_array_initializer_expression = false +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = false +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = true +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = true +ij_java_align_multiline_parameters_in_calls = false +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = true +ij_java_align_multiline_ternary_operation = false +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = false +ij_java_array_initializer_right_brace_on_new_line = false +ij_java_array_initializer_wrap = off +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = false +ij_java_binary_operation_wrap = off +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_add_space = false +ij_java_block_comment_at_first_column = true +ij_java_builder_methods = none +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = off +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 99 +ij_java_class_names_in_javadoc = 1 +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = false +ij_java_do_while_brace_force = never +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_enum_constants_wrap = off +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = off +ij_java_field_annotation_wrap = split_into_lines +ij_java_finally_on_new_line = false +ij_java_for_brace_force = never +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = off +ij_java_generate_final_locals = false +ij_java_generate_final_parameters = false +ij_java_if_brace_force = never +ij_java_imports_layout = $android.**, $androidx.**, $com.**, $junit.**, $net.**, $org.**, $java.**, $javax.**, $*, |, android.**, |, androidx.**, |, com.**, |, junit.**, |, net.**, |, org.**, |, java.**, |, javax.**, |, *, | +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = false +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 2 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_builder_methods_indents = false +ij_java_keep_control_statement_in_one_line = true +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_at_first_column = true +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = off +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = off +ij_java_modifier_list_wrap = false +ij_java_names_count_to_use_import_on_demand = 99 +ij_java_new_line_after_lparen_in_record_header = false +ij_java_parameter_annotation_wrap = off +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_record_header = false +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_record_header = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = false +ij_java_ternary_operation_wrap = off +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = off +ij_java_throws_list_wrap = off +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = off +ij_java_visibility = public +ij_java_while_brace_force = never +ij_java_while_on_new_line = false +ij_java_wrap_comments = false +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false + +[*.properties] +ij_properties_align_group_field_declarations = false +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = false + +[.editorconfig] +ij_editorconfig_align_group_field_declarations = false +ij_editorconfig_space_after_colon = false +ij_editorconfig_space_after_comma = true +ij_editorconfig_space_before_colon = false +ij_editorconfig_space_before_comma = false +ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] +ij_continuation_indent_size = 4 +ij_xml_align_attributes = false +ij_xml_align_text = false +ij_xml_attribute_wrap = normal +ij_xml_block_comment_add_space = false +ij_xml_block_comment_at_first_column = true +ij_xml_keep_blank_lines = 2 +ij_xml_keep_indents_on_empty_lines = false +ij_xml_keep_line_breaks = false +ij_xml_keep_line_breaks_in_text = true +ij_xml_keep_whitespaces = false +ij_xml_keep_whitespaces_around_cdata = preserve +ij_xml_keep_whitespaces_inside_cdata = false +ij_xml_line_comment_at_first_column = true +ij_xml_space_after_tag_name = false +ij_xml_space_around_equals_in_attribute = false +ij_xml_space_inside_empty_tag = true +ij_xml_text_wrap = normal +ij_xml_use_custom_settings = true + +[{*.apinotes,*.yaml,*.yml}] +indent_size = 2 +ij_yaml_align_values_properties = do_not_align +ij_yaml_autoinsert_sequence_marker = true +ij_yaml_block_mapping_on_new_line = false +ij_yaml_indent_sequence_value = true +ij_yaml_keep_indents_on_empty_lines = false +ij_yaml_keep_line_breaks = true +ij_yaml_sequence_on_new_line = false +ij_yaml_space_before_colon = false +ij_yaml_spaces_within_braces = true +ij_yaml_spaces_within_brackets = true + +[{*.bash,*.sh,*.zsh}] +indent_size = 2 +tab_width = 2 +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = false +ij_shell_use_unix_line_separator = true + +[{*.c,*.c++,*.cc,*.cp,*.cpp,*.cu,*.cuh,*.cxx,*.h,*.h++,*.hh,*.hp,*.hpp,*.hxx,*.i,*.icc,*.ii,*.inl,*.ino,*.ipp,*.m,*.mm,*.pch,*.tcc,*.tpp}] +ij_c_add_brief_tag = false +ij_c_add_getter_prefix = true +ij_c_add_setter_prefix = true +ij_c_align_dictionary_pair_values = false +ij_c_align_group_field_declarations = false +ij_c_align_init_list_in_columns = true +ij_c_align_multiline_array_initializer_expression = true +ij_c_align_multiline_assignment = true +ij_c_align_multiline_binary_operation = true +ij_c_align_multiline_chained_methods = false +ij_c_align_multiline_for = true +ij_c_align_multiline_ternary_operation = true +ij_c_array_initializer_comma_on_next_line = false +ij_c_array_initializer_new_line_after_left_brace = false +ij_c_array_initializer_right_brace_on_new_line = false +ij_c_array_initializer_wrap = normal +ij_c_assignment_wrap = off +ij_c_binary_operation_sign_on_next_line = false +ij_c_binary_operation_wrap = normal +ij_c_blank_lines_after_class_header = 0 +ij_c_blank_lines_after_imports = 1 +ij_c_blank_lines_around_class = 1 +ij_c_blank_lines_around_field = 0 +ij_c_blank_lines_around_field_in_interface = 0 +ij_c_blank_lines_around_method = 1 +ij_c_blank_lines_around_method_in_interface = 1 +ij_c_blank_lines_around_namespace = 0 +ij_c_blank_lines_around_properties_in_declaration = 0 +ij_c_blank_lines_around_properties_in_interface = 0 +ij_c_blank_lines_before_imports = 1 +ij_c_blank_lines_before_method_body = 0 +ij_c_block_brace_placement = end_of_line +ij_c_block_brace_style = end_of_line +ij_c_block_comment_at_first_column = true +ij_c_catch_on_new_line = false +ij_c_class_brace_style = end_of_line +ij_c_class_constructor_init_list_align_multiline = true +ij_c_class_constructor_init_list_comma_on_next_line = false +ij_c_class_constructor_init_list_new_line_after_colon = never +ij_c_class_constructor_init_list_new_line_before_colon = if_long +ij_c_class_constructor_init_list_wrap = normal +ij_c_copy_is_deep = false +ij_c_create_interface_for_categories = true +ij_c_declare_generated_methods = true +ij_c_description_include_member_names = true +ij_c_discharged_short_ternary_operator = false +ij_c_do_not_add_breaks = false +ij_c_do_while_brace_force = never +ij_c_else_on_new_line = false +ij_c_enum_constants_comma_on_next_line = false +ij_c_enum_constants_wrap = on_every_item +ij_c_for_brace_force = never +ij_c_for_statement_new_line_after_left_paren = false +ij_c_for_statement_right_paren_on_new_line = false +ij_c_for_statement_wrap = off +ij_c_function_brace_placement = end_of_line +ij_c_function_call_arguments_align_multiline = true +ij_c_function_call_arguments_align_multiline_pars = false +ij_c_function_call_arguments_comma_on_next_line = false +ij_c_function_call_arguments_new_line_after_lpar = false +ij_c_function_call_arguments_new_line_before_rpar = false +ij_c_function_call_arguments_wrap = normal +ij_c_function_non_top_after_return_type_wrap = normal +ij_c_function_parameters_align_multiline = true +ij_c_function_parameters_align_multiline_pars = false +ij_c_function_parameters_comma_on_next_line = false +ij_c_function_parameters_new_line_after_lpar = false +ij_c_function_parameters_new_line_before_rpar = false +ij_c_function_parameters_wrap = normal +ij_c_function_top_after_return_type_wrap = normal +ij_c_generate_additional_eq_operators = true +ij_c_generate_additional_rel_operators = true +ij_c_generate_class_constructor = true +ij_c_generate_comparison_operators_use_std_tie = false +ij_c_generate_instance_variables_for_properties = ask +ij_c_generate_operators_as_members = true +ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT} +ij_c_if_brace_force = never +ij_c_in_line_short_ternary_operator = true +ij_c_indent_block_comment = true +ij_c_indent_c_struct_members = 4 +ij_c_indent_case_from_switch = true +ij_c_indent_class_members = 4 +ij_c_indent_directive_as_code = false +ij_c_indent_implementation_members = 0 +ij_c_indent_inside_code_block = 4 +ij_c_indent_interface_members = 0 +ij_c_indent_interface_members_except_ivars_block = false +ij_c_indent_namespace_members = 4 +ij_c_indent_preprocessor_directive = 0 +ij_c_indent_visibility_keywords = 0 +ij_c_insert_override = true +ij_c_insert_virtual_with_override = false +ij_c_introduce_auto_vars = false +ij_c_introduce_const_params = false +ij_c_introduce_const_vars = false +ij_c_introduce_generate_property = false +ij_c_introduce_generate_synthesize = true +ij_c_introduce_globals_to_header = true +ij_c_introduce_prop_to_private_category = false +ij_c_introduce_static_consts = true +ij_c_introduce_use_ns_types = false +ij_c_ivars_prefix = _ +ij_c_keep_blank_lines_before_end = 2 +ij_c_keep_blank_lines_before_right_brace = 2 +ij_c_keep_blank_lines_in_code = 2 +ij_c_keep_blank_lines_in_declarations = 2 +ij_c_keep_case_expressions_in_one_line = false +ij_c_keep_control_statement_in_one_line = true +ij_c_keep_directive_at_first_column = true +ij_c_keep_first_column_comment = true +ij_c_keep_line_breaks = true +ij_c_keep_nested_namespaces_in_one_line = false +ij_c_keep_simple_blocks_in_one_line = true +ij_c_keep_simple_methods_in_one_line = true +ij_c_keep_structures_in_one_line = false +ij_c_lambda_capture_list_align_multiline = false +ij_c_lambda_capture_list_align_multiline_bracket = false +ij_c_lambda_capture_list_comma_on_next_line = false +ij_c_lambda_capture_list_new_line_after_lbracket = false +ij_c_lambda_capture_list_new_line_before_rbracket = false +ij_c_lambda_capture_list_wrap = off +ij_c_line_comment_add_space = false +ij_c_line_comment_at_first_column = true +ij_c_method_brace_placement = end_of_line +ij_c_method_call_arguments_align_by_colons = true +ij_c_method_call_arguments_align_multiline = false +ij_c_method_call_arguments_special_dictionary_pairs_treatment = true +ij_c_method_call_arguments_wrap = off +ij_c_method_call_chain_wrap = off +ij_c_method_parameters_align_by_colons = true +ij_c_method_parameters_align_multiline = false +ij_c_method_parameters_wrap = off +ij_c_namespace_brace_placement = end_of_line +ij_c_parentheses_expression_new_line_after_left_paren = false +ij_c_parentheses_expression_right_paren_on_new_line = false +ij_c_place_assignment_sign_on_next_line = false +ij_c_property_nonatomic = true +ij_c_put_ivars_to_implementation = true +ij_c_refactor_compatibility_aliases_and_classes = true +ij_c_refactor_properties_and_ivars = true +ij_c_release_style = ivar +ij_c_retain_object_parameters_in_constructor = true +ij_c_semicolon_after_method_signature = false +ij_c_shift_operation_align_multiline = true +ij_c_shift_operation_wrap = normal +ij_c_show_non_virtual_functions = false +ij_c_space_after_colon = true +ij_c_space_after_colon_in_foreach = true +ij_c_space_after_colon_in_selector = false +ij_c_space_after_comma = true +ij_c_space_after_cup_in_blocks = false +ij_c_space_after_dictionary_literal_colon = true +ij_c_space_after_for_semicolon = true +ij_c_space_after_init_list_colon = true +ij_c_space_after_method_parameter_type_parentheses = false +ij_c_space_after_method_return_type_parentheses = false +ij_c_space_after_pointer_in_declaration = false +ij_c_space_after_quest = true +ij_c_space_after_reference_in_declaration = false +ij_c_space_after_reference_in_rvalue = false +ij_c_space_after_structures_rbrace = true +ij_c_space_after_superclass_colon = true +ij_c_space_after_type_cast = true +ij_c_space_after_visibility_sign_in_method_declaration = true +ij_c_space_before_autorelease_pool_lbrace = true +ij_c_space_before_catch_keyword = true +ij_c_space_before_catch_left_brace = true +ij_c_space_before_catch_parentheses = true +ij_c_space_before_category_parentheses = true +ij_c_space_before_chained_send_message = true +ij_c_space_before_class_left_brace = true +ij_c_space_before_colon = true +ij_c_space_before_colon_in_foreach = false +ij_c_space_before_comma = false +ij_c_space_before_dictionary_literal_colon = false +ij_c_space_before_do_left_brace = true +ij_c_space_before_else_keyword = true +ij_c_space_before_else_left_brace = true +ij_c_space_before_for_left_brace = true +ij_c_space_before_for_parentheses = true +ij_c_space_before_for_semicolon = false +ij_c_space_before_if_left_brace = true +ij_c_space_before_if_parentheses = true +ij_c_space_before_init_list = false +ij_c_space_before_init_list_colon = true +ij_c_space_before_method_call_parentheses = false +ij_c_space_before_method_left_brace = true +ij_c_space_before_method_parentheses = false +ij_c_space_before_namespace_lbrace = true +ij_c_space_before_pointer_in_declaration = true +ij_c_space_before_property_attributes_parentheses = false +ij_c_space_before_protocols_brackets = true +ij_c_space_before_quest = true +ij_c_space_before_reference_in_declaration = true +ij_c_space_before_superclass_colon = true +ij_c_space_before_switch_left_brace = true +ij_c_space_before_switch_parentheses = true +ij_c_space_before_template_call_lt = false +ij_c_space_before_template_declaration_lt = false +ij_c_space_before_try_left_brace = true +ij_c_space_before_while_keyword = true +ij_c_space_before_while_left_brace = true +ij_c_space_before_while_parentheses = true +ij_c_space_between_adjacent_brackets = false +ij_c_space_between_operator_and_punctuator = false +ij_c_space_within_empty_array_initializer_braces = false +ij_c_spaces_around_additive_operators = true +ij_c_spaces_around_assignment_operators = true +ij_c_spaces_around_bitwise_operators = true +ij_c_spaces_around_equality_operators = true +ij_c_spaces_around_lambda_arrow = true +ij_c_spaces_around_logical_operators = true +ij_c_spaces_around_multiplicative_operators = true +ij_c_spaces_around_pm_operators = false +ij_c_spaces_around_relational_operators = true +ij_c_spaces_around_shift_operators = true +ij_c_spaces_around_unary_operator = false +ij_c_spaces_within_array_initializer_braces = false +ij_c_spaces_within_braces = true +ij_c_spaces_within_brackets = false +ij_c_spaces_within_cast_parentheses = false +ij_c_spaces_within_catch_parentheses = false +ij_c_spaces_within_category_parentheses = false +ij_c_spaces_within_empty_braces = false +ij_c_spaces_within_empty_function_call_parentheses = false +ij_c_spaces_within_empty_function_declaration_parentheses = false +ij_c_spaces_within_empty_lambda_capture_list_bracket = false +ij_c_spaces_within_empty_template_call_ltgt = false +ij_c_spaces_within_empty_template_declaration_ltgt = false +ij_c_spaces_within_for_parentheses = false +ij_c_spaces_within_function_call_parentheses = false +ij_c_spaces_within_function_declaration_parentheses = false +ij_c_spaces_within_if_parentheses = false +ij_c_spaces_within_lambda_capture_list_bracket = false +ij_c_spaces_within_method_parameter_type_parentheses = false +ij_c_spaces_within_method_return_type_parentheses = false +ij_c_spaces_within_parentheses = false +ij_c_spaces_within_property_attributes_parentheses = false +ij_c_spaces_within_protocols_brackets = false +ij_c_spaces_within_send_message_brackets = false +ij_c_spaces_within_switch_parentheses = false +ij_c_spaces_within_template_call_ltgt = false +ij_c_spaces_within_template_declaration_ltgt = false +ij_c_spaces_within_template_double_gt = true +ij_c_spaces_within_while_parentheses = false +ij_c_special_else_if_treatment = true +ij_c_superclass_list_after_colon = never +ij_c_superclass_list_align_multiline = true +ij_c_superclass_list_before_colon = if_long +ij_c_superclass_list_comma_on_next_line = false +ij_c_superclass_list_wrap = on_every_item +ij_c_tag_prefix_of_block_comment = at +ij_c_tag_prefix_of_line_comment = back_slash +ij_c_template_call_arguments_align_multiline = false +ij_c_template_call_arguments_align_multiline_pars = false +ij_c_template_call_arguments_comma_on_next_line = false +ij_c_template_call_arguments_new_line_after_lt = false +ij_c_template_call_arguments_new_line_before_gt = false +ij_c_template_call_arguments_wrap = off +ij_c_template_declaration_function_body_indent = false +ij_c_template_declaration_function_wrap = split_into_lines +ij_c_template_declaration_struct_body_indent = false +ij_c_template_declaration_struct_wrap = split_into_lines +ij_c_template_parameters_align_multiline = false +ij_c_template_parameters_align_multiline_pars = false +ij_c_template_parameters_comma_on_next_line = false +ij_c_template_parameters_new_line_after_lt = false +ij_c_template_parameters_new_line_before_gt = false +ij_c_template_parameters_wrap = off +ij_c_ternary_operation_signs_on_next_line = true +ij_c_ternary_operation_wrap = normal +ij_c_type_qualifiers_placement = before +ij_c_use_modern_casts = true +ij_c_use_setters_in_constructor = true +ij_c_while_brace_force = never +ij_c_while_on_new_line = false +ij_c_wrap_property_declaration = off + +[{*.cmake,CMakeLists.txt}] +ij_cmake_align_multiline_parameters_in_calls = false +ij_cmake_force_commands_case = 2 +ij_cmake_keep_blank_lines_in_code = 2 +ij_cmake_space_before_for_parentheses = true +ij_cmake_space_before_if_parentheses = true +ij_cmake_space_before_method_call_parentheses = false +ij_cmake_space_before_method_parentheses = false +ij_cmake_space_before_while_parentheses = true +ij_cmake_spaces_within_for_parentheses = false +ij_cmake_spaces_within_if_parentheses = false +ij_cmake_spaces_within_method_call_parentheses = false +ij_cmake_spaces_within_method_parentheses = false +ij_cmake_spaces_within_while_parentheses = false + +[{*.gant,*.groovy,*.gy}] +ij_groovy_align_group_field_declarations = false +ij_groovy_align_multiline_array_initializer_expression = false +ij_groovy_align_multiline_assignment = false +ij_groovy_align_multiline_binary_operation = false +ij_groovy_align_multiline_chained_methods = false +ij_groovy_align_multiline_extends_list = false +ij_groovy_align_multiline_for = true +ij_groovy_align_multiline_list_or_map = true +ij_groovy_align_multiline_method_parentheses = false +ij_groovy_align_multiline_parameters = true +ij_groovy_align_multiline_parameters_in_calls = false +ij_groovy_align_multiline_resources = true +ij_groovy_align_multiline_ternary_operation = false +ij_groovy_align_multiline_throws_list = false +ij_groovy_align_named_args_in_map = true +ij_groovy_align_throws_keyword = false +ij_groovy_array_initializer_new_line_after_left_brace = false +ij_groovy_array_initializer_right_brace_on_new_line = false +ij_groovy_array_initializer_wrap = off +ij_groovy_assert_statement_wrap = off +ij_groovy_assignment_wrap = off +ij_groovy_binary_operation_wrap = off +ij_groovy_blank_lines_after_class_header = 0 +ij_groovy_blank_lines_after_imports = 1 +ij_groovy_blank_lines_after_package = 1 +ij_groovy_blank_lines_around_class = 1 +ij_groovy_blank_lines_around_field = 0 +ij_groovy_blank_lines_around_field_in_interface = 0 +ij_groovy_blank_lines_around_method = 1 +ij_groovy_blank_lines_around_method_in_interface = 1 +ij_groovy_blank_lines_before_imports = 1 +ij_groovy_blank_lines_before_method_body = 0 +ij_groovy_blank_lines_before_package = 0 +ij_groovy_block_brace_style = end_of_line +ij_groovy_block_comment_add_space = false +ij_groovy_block_comment_at_first_column = true +ij_groovy_call_parameters_new_line_after_left_paren = false +ij_groovy_call_parameters_right_paren_on_new_line = false +ij_groovy_call_parameters_wrap = off +ij_groovy_catch_on_new_line = false +ij_groovy_class_annotation_wrap = split_into_lines +ij_groovy_class_brace_style = end_of_line +ij_groovy_class_count_to_use_import_on_demand = 5 +ij_groovy_do_while_brace_force = never +ij_groovy_else_on_new_line = false +ij_groovy_enum_constants_wrap = off +ij_groovy_extends_keyword_wrap = off +ij_groovy_extends_list_wrap = off +ij_groovy_field_annotation_wrap = split_into_lines +ij_groovy_finally_on_new_line = false +ij_groovy_for_brace_force = never +ij_groovy_for_statement_new_line_after_left_paren = false +ij_groovy_for_statement_right_paren_on_new_line = false +ij_groovy_for_statement_wrap = off +ij_groovy_if_brace_force = never +ij_groovy_import_annotation_wrap = 2 +ij_groovy_imports_layout = *, |, javax.**, java.**, |, $* +ij_groovy_indent_case_from_switch = true +ij_groovy_indent_label_blocks = true +ij_groovy_insert_inner_class_imports = false +ij_groovy_keep_blank_lines_before_right_brace = 2 +ij_groovy_keep_blank_lines_in_code = 2 +ij_groovy_keep_blank_lines_in_declarations = 2 +ij_groovy_keep_control_statement_in_one_line = true +ij_groovy_keep_first_column_comment = true +ij_groovy_keep_indents_on_empty_lines = false +ij_groovy_keep_line_breaks = true +ij_groovy_keep_multiple_expressions_in_one_line = false +ij_groovy_keep_simple_blocks_in_one_line = false +ij_groovy_keep_simple_classes_in_one_line = true +ij_groovy_keep_simple_lambdas_in_one_line = true +ij_groovy_keep_simple_methods_in_one_line = true +ij_groovy_label_indent_absolute = false +ij_groovy_label_indent_size = 0 +ij_groovy_lambda_brace_style = end_of_line +ij_groovy_layout_static_imports_separately = true +ij_groovy_line_comment_add_space = false +ij_groovy_line_comment_at_first_column = true +ij_groovy_method_annotation_wrap = split_into_lines +ij_groovy_method_brace_style = end_of_line +ij_groovy_method_call_chain_wrap = off +ij_groovy_method_parameters_new_line_after_left_paren = false +ij_groovy_method_parameters_right_paren_on_new_line = false +ij_groovy_method_parameters_wrap = off +ij_groovy_modifier_list_wrap = false +ij_groovy_names_count_to_use_import_on_demand = 3 +ij_groovy_packages_to_use_import_on_demand = java.awt.*, javax.swing.* +ij_groovy_parameter_annotation_wrap = off +ij_groovy_parentheses_expression_new_line_after_left_paren = false +ij_groovy_parentheses_expression_right_paren_on_new_line = false +ij_groovy_prefer_parameters_wrap = false +ij_groovy_resource_list_new_line_after_left_paren = false +ij_groovy_resource_list_right_paren_on_new_line = false +ij_groovy_resource_list_wrap = off +ij_groovy_space_after_assert_separator = true +ij_groovy_space_after_colon = true +ij_groovy_space_after_comma = true +ij_groovy_space_after_comma_in_type_arguments = true +ij_groovy_space_after_for_semicolon = true +ij_groovy_space_after_quest = true +ij_groovy_space_after_type_cast = true +ij_groovy_space_before_annotation_parameter_list = false +ij_groovy_space_before_array_initializer_left_brace = false +ij_groovy_space_before_assert_separator = false +ij_groovy_space_before_catch_keyword = true +ij_groovy_space_before_catch_left_brace = true +ij_groovy_space_before_catch_parentheses = true +ij_groovy_space_before_class_left_brace = true +ij_groovy_space_before_closure_left_brace = true +ij_groovy_space_before_colon = true +ij_groovy_space_before_comma = false +ij_groovy_space_before_do_left_brace = true +ij_groovy_space_before_else_keyword = true +ij_groovy_space_before_else_left_brace = true +ij_groovy_space_before_finally_keyword = true +ij_groovy_space_before_finally_left_brace = true +ij_groovy_space_before_for_left_brace = true +ij_groovy_space_before_for_parentheses = true +ij_groovy_space_before_for_semicolon = false +ij_groovy_space_before_if_left_brace = true +ij_groovy_space_before_if_parentheses = true +ij_groovy_space_before_method_call_parentheses = false +ij_groovy_space_before_method_left_brace = true +ij_groovy_space_before_method_parentheses = false +ij_groovy_space_before_quest = true +ij_groovy_space_before_record_parentheses = false +ij_groovy_space_before_switch_left_brace = true +ij_groovy_space_before_switch_parentheses = true +ij_groovy_space_before_synchronized_left_brace = true +ij_groovy_space_before_synchronized_parentheses = true +ij_groovy_space_before_try_left_brace = true +ij_groovy_space_before_try_parentheses = true +ij_groovy_space_before_while_keyword = true +ij_groovy_space_before_while_left_brace = true +ij_groovy_space_before_while_parentheses = true +ij_groovy_space_in_named_argument = true +ij_groovy_space_in_named_argument_before_colon = false +ij_groovy_space_within_empty_array_initializer_braces = false +ij_groovy_space_within_empty_method_call_parentheses = false +ij_groovy_spaces_around_additive_operators = true +ij_groovy_spaces_around_assignment_operators = true +ij_groovy_spaces_around_bitwise_operators = true +ij_groovy_spaces_around_equality_operators = true +ij_groovy_spaces_around_lambda_arrow = true +ij_groovy_spaces_around_logical_operators = true +ij_groovy_spaces_around_multiplicative_operators = true +ij_groovy_spaces_around_regex_operators = true +ij_groovy_spaces_around_relational_operators = true +ij_groovy_spaces_around_shift_operators = true +ij_groovy_spaces_within_annotation_parentheses = false +ij_groovy_spaces_within_array_initializer_braces = false +ij_groovy_spaces_within_braces = true +ij_groovy_spaces_within_brackets = false +ij_groovy_spaces_within_cast_parentheses = false +ij_groovy_spaces_within_catch_parentheses = false +ij_groovy_spaces_within_for_parentheses = false +ij_groovy_spaces_within_gstring_injection_braces = false +ij_groovy_spaces_within_if_parentheses = false +ij_groovy_spaces_within_list_or_map = false +ij_groovy_spaces_within_method_call_parentheses = false +ij_groovy_spaces_within_method_parentheses = false +ij_groovy_spaces_within_parentheses = false +ij_groovy_spaces_within_switch_parentheses = false +ij_groovy_spaces_within_synchronized_parentheses = false +ij_groovy_spaces_within_try_parentheses = false +ij_groovy_spaces_within_tuple_expression = false +ij_groovy_spaces_within_while_parentheses = false +ij_groovy_special_else_if_treatment = true +ij_groovy_ternary_operation_wrap = off +ij_groovy_throws_keyword_wrap = off +ij_groovy_throws_list_wrap = off +ij_groovy_use_flying_geese_braces = false +ij_groovy_use_fq_class_names = false +ij_groovy_use_fq_class_names_in_javadoc = true +ij_groovy_use_relative_indents = false +ij_groovy_use_single_class_imports = true +ij_groovy_variable_annotation_wrap = off +ij_groovy_while_brace_force = never +ij_groovy_while_on_new_line = false +ij_groovy_wrap_chain_calls_after_dot = false +ij_groovy_wrap_long_lines = false + +[{*.gradle.kts,*.kt,*.kts,*.main.kts}] +ij_kotlin_align_in_columns_case_branch = false +ij_kotlin_align_multiline_binary_operation = false +ij_kotlin_align_multiline_extends_list = false +ij_kotlin_align_multiline_method_parentheses = false +ij_kotlin_align_multiline_parameters = true +ij_kotlin_align_multiline_parameters_in_calls = false +ij_kotlin_allow_trailing_comma = false +ij_kotlin_allow_trailing_comma_on_call_site = false +ij_kotlin_assignment_wrap = off +ij_kotlin_blank_lines_after_class_header = 0 +ij_kotlin_blank_lines_around_block_when_branches = 0 +ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1 +ij_kotlin_block_comment_add_space = false +ij_kotlin_block_comment_at_first_column = true +ij_kotlin_call_parameters_new_line_after_left_paren = false +ij_kotlin_call_parameters_right_paren_on_new_line = false +ij_kotlin_call_parameters_wrap = off +ij_kotlin_catch_on_new_line = false +ij_kotlin_class_annotation_wrap = split_into_lines +ij_kotlin_continuation_indent_for_chained_calls = true +ij_kotlin_continuation_indent_for_expression_bodies = true +ij_kotlin_continuation_indent_in_argument_lists = true +ij_kotlin_continuation_indent_in_elvis = true +ij_kotlin_continuation_indent_in_if_conditions = true +ij_kotlin_continuation_indent_in_parameter_lists = true +ij_kotlin_continuation_indent_in_supertype_lists = true +ij_kotlin_else_on_new_line = false +ij_kotlin_enum_constants_wrap = off +ij_kotlin_extends_list_wrap = off +ij_kotlin_field_annotation_wrap = split_into_lines +ij_kotlin_finally_on_new_line = false +ij_kotlin_if_rparen_on_new_line = false +ij_kotlin_import_nested_classes = false +ij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^ +ij_kotlin_insert_whitespaces_in_simple_one_line_method = true +ij_kotlin_keep_blank_lines_before_right_brace = 2 +ij_kotlin_keep_blank_lines_in_code = 2 +ij_kotlin_keep_blank_lines_in_declarations = 2 +ij_kotlin_keep_first_column_comment = true +ij_kotlin_keep_indents_on_empty_lines = false +ij_kotlin_keep_line_breaks = true +ij_kotlin_lbrace_on_next_line = false +ij_kotlin_line_comment_add_space = false +ij_kotlin_line_comment_at_first_column = true +ij_kotlin_method_annotation_wrap = split_into_lines +ij_kotlin_method_call_chain_wrap = off +ij_kotlin_method_parameters_new_line_after_left_paren = false +ij_kotlin_method_parameters_right_paren_on_new_line = false +ij_kotlin_method_parameters_wrap = off +ij_kotlin_name_count_to_use_star_import = 5 +ij_kotlin_name_count_to_use_star_import_for_members = 3 +ij_kotlin_packages_to_use_import_on_demand = java.util.*, kotlinx.android.synthetic.**, io.ktor.** +ij_kotlin_parameter_annotation_wrap = off +ij_kotlin_space_after_comma = true +ij_kotlin_space_after_extend_colon = true +ij_kotlin_space_after_type_colon = true +ij_kotlin_space_before_catch_parentheses = true +ij_kotlin_space_before_comma = false +ij_kotlin_space_before_extend_colon = true +ij_kotlin_space_before_for_parentheses = true +ij_kotlin_space_before_if_parentheses = true +ij_kotlin_space_before_lambda_arrow = true +ij_kotlin_space_before_type_colon = false +ij_kotlin_space_before_when_parentheses = true +ij_kotlin_space_before_while_parentheses = true +ij_kotlin_spaces_around_additive_operators = true +ij_kotlin_spaces_around_assignment_operators = true +ij_kotlin_spaces_around_equality_operators = true +ij_kotlin_spaces_around_function_type_arrow = true +ij_kotlin_spaces_around_logical_operators = true +ij_kotlin_spaces_around_multiplicative_operators = true +ij_kotlin_spaces_around_range = false +ij_kotlin_spaces_around_relational_operators = true +ij_kotlin_spaces_around_unary_operator = false +ij_kotlin_spaces_around_when_arrow = true +ij_kotlin_use_custom_formatting_for_modifiers = true +ij_kotlin_variable_annotation_wrap = off +ij_kotlin_while_on_new_line = false +ij_kotlin_wrap_elvis_expressions = 1 +ij_kotlin_wrap_expression_body_functions = 0 +ij_kotlin_wrap_first_method_in_call_chain = false + +[{*.har,*.json}] +indent_size = 2 +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = true +ij_json_space_before_comma = false +ij_json_spaces_within_braces = false +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false + +[{*.htm,*.html,*.sht,*.shtm,*.shtml}] +ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3 +ij_html_align_attributes = true +ij_html_align_text = false +ij_html_attribute_wrap = normal +ij_html_block_comment_add_space = false +ij_html_block_comment_at_first_column = true +ij_html_do_not_align_children_of_min_lines = 0 +ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p +ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot +ij_html_enforce_quotes = false +ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var +ij_html_keep_blank_lines = 2 +ij_html_keep_indents_on_empty_lines = false +ij_html_keep_line_breaks = true +ij_html_keep_line_breaks_in_text = true +ij_html_keep_whitespaces = false +ij_html_keep_whitespaces_inside = span, pre, textarea +ij_html_line_comment_at_first_column = true +ij_html_new_line_after_last_attribute = never +ij_html_new_line_before_first_attribute = never +ij_html_quote_style = double +ij_html_remove_new_line_before_tags = br +ij_html_space_after_tag_name = false +ij_html_space_around_equality_in_attribute = false +ij_html_space_inside_empty_tag = false +ij_html_text_wrap = normal + +[{*.markdown,*.md}] +ij_markdown_force_one_space_after_blockquote_symbol = true +ij_markdown_force_one_space_after_header_symbol = true +ij_markdown_force_one_space_after_list_bullet = true +ij_markdown_force_one_space_between_words = true +ij_markdown_keep_indents_on_empty_lines = false +ij_markdown_max_lines_around_block_elements = 1 +ij_markdown_max_lines_around_header = 1 +ij_markdown_max_lines_between_paragraphs = 1 +ij_markdown_min_lines_around_block_elements = 1 +ij_markdown_min_lines_around_header = 1 +ij_markdown_min_lines_between_paragraphs = 1 + +[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}] +ij_toml_keep_indents_on_empty_lines = false diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 58dbda0..c4a206e 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -13,7 +13,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview -import de.markusressel.kodeeditor.library.KodeEditor +import de.markusressel.kodeeditor.library.compose.KodeEditor import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle diff --git a/library/build.gradle b/library/build.gradle index 69c2abc..08a871c 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -60,6 +60,8 @@ dependencies { changing = true } + debugImplementation "com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt similarity index 55% rename from library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt rename to library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index f6c629b..5714ecc 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -1,22 +1,52 @@ -package de.markusressel.kodeeditor.library +package de.markusressel.kodeeditor.library.compose -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.produceState +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import de.markusressel.kodehighlighter.core.ui.KodeTextField import de.markusressel.kodehighlighter.core.ui.KodeTextFieldColors import de.markusressel.kodehighlighter.core.ui.KodeTextFieldDefaults +import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook +import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle + +@Preview +@Composable +fun KodeEditorPreview() { + var text by remember { + val initialText = """ + # Hello World + Code: `readResourceFileAsText(R.raw.sample_text)` + """.trimIndent() + mutableStateOf(TextFieldValue( + text = initialText + )) + } + + val languageRuleBook by remember { + mutableStateOf(MarkdownRuleBook()) + } + val colorScheme by remember { + mutableStateOf(DarkBackgroundColorSchemeWithSpanStyle()) + } + + KodeEditor( + text = text, + languageRuleBook = languageRuleBook, + colorScheme = colorScheme, + onValueChange = { text = it } + ) +} /** * Compose version of the KodeEditorLayout @@ -37,8 +67,8 @@ fun KodeEditor( ) { LineNumbers( text = text.text, - colors = colors, - enabled = enabled, + textColor = Color.White, + backgroundColor = colors.backgroundColor(enabled = enabled).value, ) KodeTextField( @@ -57,25 +87,3 @@ fun KodeEditor( } } } - -@Composable -fun LineNumbers( - text: String, - colors: KodeTextFieldColors, - enabled: Boolean, -) { - val lineNumbers by produceState("") { - val lineCount = text.lines().size - value = (1..lineCount).joinToString(separator = "\n") - } - - Text( - modifier = Modifier - .wrapContentWidth() - .background(color = colors.backgroundColor(enabled = enabled).value) - .padding(start = 4.dp, end = 4.dp), - text = lineNumbers, - textAlign = TextAlign.End, - ) -} - diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt new file mode 100644 index 0000000..73e38b4 --- /dev/null +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt @@ -0,0 +1,51 @@ +package de.markusressel.kodeeditor.library.compose + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + + +@Preview +@Composable +fun LineNumbersPreview() { + val text = (1..10).joinToString(separator = "\n", prefix = "Line: ") + LineNumbers( + text = text, + backgroundColor = Color.White, + textColor = Color.Black, + ) +} + +@Composable +fun LineNumbers( + text: String, + backgroundColor: Color, + textColor: Color = Color.Unspecified, +) { + val lineNumbers by remember { + val lineCount = text.lines().size + val lineText = (1..lineCount).joinToString(separator = "\n") + mutableStateOf(lineText) + } + + Text( + modifier = Modifier + .wrapContentWidth() + .background(color = backgroundColor) + .padding(start = 4.dp, end = 4.dp), + text = lineNumbers, + color = textColor, + textAlign = TextAlign.End, + ) +} + diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt similarity index 98% rename from library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt rename to library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt index 61860f1..1e77646 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor.library +package de.markusressel.kodeeditor.library.compose import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTransformGestures From eb3bb7614ce053b26eb3728ea9a475ab6f9cf7c3 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 9 Oct 2022 16:21:19 +0200 Subject: [PATCH 14/62] added KodeEditorColors for easier color specification of different parts of the KodeEditor --- .../kodeeditor/library/compose/KodeEditor.kt | 11 +-- .../library/compose/KodeEditorColors.kt | 88 +++++++++++++++++++ 2 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 5714ecc..8a16771 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview @@ -15,8 +14,6 @@ import androidx.compose.ui.unit.dp import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import de.markusressel.kodehighlighter.core.ui.KodeTextField -import de.markusressel.kodehighlighter.core.ui.KodeTextFieldColors -import de.markusressel.kodehighlighter.core.ui.KodeTextFieldDefaults import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle @@ -58,7 +55,7 @@ fun KodeEditor( languageRuleBook: LanguageRuleBook, colorScheme: ColorScheme, onValueChange: (TextFieldValue) -> Unit, - colors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), + colors: KodeEditorColors = KodeEditorDefaults.editorColors(), enabled: Boolean = true, ) { ZoomLayout(modifier = modifier) { @@ -67,8 +64,8 @@ fun KodeEditor( ) { LineNumbers( text = text.text, - textColor = Color.White, - backgroundColor = colors.backgroundColor(enabled = enabled).value, + textColor = colors.lineNumberTextColor().value, + backgroundColor = colors.lineNumberBackgroundColor().value, ) KodeTextField( @@ -82,7 +79,7 @@ fun KodeEditor( languageRuleBook = languageRuleBook, colorScheme = colorScheme, onValueChange = onValueChange, - colors = colors, + colors = colors.textFieldColors(enabled = enabled).value, ) } } diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt new file mode 100644 index 0000000..b456231 --- /dev/null +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt @@ -0,0 +1,88 @@ +package de.markusressel.kodeeditor.library.compose + +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.* +import androidx.compose.ui.graphics.Color +import de.markusressel.kodehighlighter.core.ui.KodeTextField +import de.markusressel.kodehighlighter.core.ui.KodeTextFieldColors +import de.markusressel.kodehighlighter.core.ui.KodeTextFieldDefaults + + +/** + * Represents the colors of the code editor (without highlighting), line numbers, etc. used + * in a code editor in different states. + * + * See [KodeEditorDefaults.editorColors] for the default colors used in [KodeEditorDefaults]. + */ +@Stable +interface KodeEditorColors { + + /** + * [KodeTextField] specific set of colors + * + * @param enabled whether the text field is enabled + */ + @Composable + fun textFieldColors(enabled: Boolean): State + + /** + * Represents the color used for line numbers text. + */ + @Composable + fun lineNumberTextColor(): State + + /** + * Represents the color used for the background of the line numbers. + */ + @Composable + fun lineNumberBackgroundColor(): State + +} + + +/** + * Contains the default values used by [KodeTextField]. + */ +@Immutable +object KodeEditorDefaults { + + /** + * Creates a [KodeEditorColors] that represents the default input text, background and content + * (including label, placeholder, leading and trailing icons) colors used in a [KodeEditor]. + */ + @Composable + fun editorColors( + textFieldColors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), + lineNumberTextColor: Color = Color.Unspecified, + lineNumberBackgroundColor: Color = MaterialTheme.colors.onSurface, + ): KodeEditorColors = + DefaultKodeEditorColors( + textFieldColors = textFieldColors, + lineNumberTextColor = lineNumberTextColor, + lineNumberBackgroundColor = lineNumberBackgroundColor, + ) +} + + +private data class DefaultKodeEditorColors( + private val textFieldColors: KodeTextFieldColors, + private val lineNumberTextColor: Color, + private val lineNumberBackgroundColor: Color, +) : KodeEditorColors { + + @Composable + override fun textFieldColors(enabled: Boolean): State { + return rememberUpdatedState(textFieldColors) + } + + @Composable + override fun lineNumberTextColor(): State { + return rememberUpdatedState(lineNumberTextColor) + } + + @Composable + override fun lineNumberBackgroundColor(): State { + return rememberUpdatedState(lineNumberBackgroundColor) + } + +} From ee81b024ad7682807c1396bd0ecddc24e7df3130 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 9 Oct 2022 20:34:57 +0200 Subject: [PATCH 15/62] refactoring to expose zoom and offset of ZoomLayout added textStyle added documentation --- .../kodeeditor/ComposeMainActivity.kt | 47 ++++++---- .../kodeeditor/library/compose/KodeEditor.kt | 54 ++++++++++-- .../kodeeditor/library/compose/LineNumbers.kt | 6 +- .../kodeeditor/library/compose/ZoomLayout.kt | 86 +++++++++---------- 4 files changed, 127 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index c4a206e..997dac1 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -4,16 +4,21 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.RawRes -import androidx.compose.foundation.layout.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.sp import de.markusressel.kodeeditor.library.compose.KodeEditor +import de.markusressel.kodeeditor.library.compose.KodeEditorDefaults import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle @@ -23,24 +28,36 @@ class ComposeMainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContent { KodeEditorTheme { - Box( - modifier = Modifier - .fillMaxSize() - .width(IntrinsicSize.Max) - .height(IntrinsicSize.Max), - ) { + var fontSize by remember { + mutableStateOf(14) + } + Column { + Row { + Button(onClick = { fontSize++ }) { + Text(text = "+") + } + + Button(onClick = { fontSize-- }) { + Text(text = "-") + } + } + var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { val initialText = readResourceFileAsText(R.raw.sample_text) mutableStateOf(TextFieldValue(initialText)) } KodeEditor( - modifier = Modifier - .matchParentSize(), + modifier = Modifier.fillMaxSize(), languageRuleBook = MarkdownRuleBook(), colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), text = text, - onValueChange = { text = it } + onValueChange = { text = it }, + textStyle = TextStyle(fontSize = fontSize.sp), + colors = KodeEditorDefaults.editorColors( + lineNumberTextColor = Color.Black, + lineNumberBackgroundColor = Color.White, + ) ) } } @@ -55,7 +72,7 @@ class ComposeMainActivity : ComponentActivity() { @Preview(showBackground = true) @Composable -fun DefaultPreview() { +private fun DefaultPreview() { KodeEditorTheme { var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { val initialText = """ diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 8a16771..99543c0 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -1,16 +1,19 @@ package de.markusressel.kodeeditor.library.compose import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material.LocalTextStyle import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import de.markusressel.kodehighlighter.core.LanguageRuleBook import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme import de.markusressel.kodehighlighter.core.ui.KodeTextField @@ -19,7 +22,7 @@ import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgro @Preview @Composable -fun KodeEditorPreview() { +private fun KodeEditorPreview() { var text by remember { val initialText = """ # Hello World @@ -47,6 +50,14 @@ fun KodeEditorPreview() { /** * Compose version of the KodeEditorLayout + * + * @param modifier compose modifiers + * @param text the current text of the editor + * @param languageRuleBook the language rule book to use for highlighting + * @param onValueChange callback for changes to the text and/or cursor selection + * @param colors the color scheme to use for highlighting + * @param textStyle the text style used for the editor text + * @param enabled whether the editor is enabled */ @Composable fun KodeEditor( @@ -56,18 +67,50 @@ fun KodeEditor( colorScheme: ColorScheme, onValueChange: (TextFieldValue) -> Unit, colors: KodeEditorColors = KodeEditorDefaults.editorColors(), + textStyle: TextStyle = LocalTextStyle.current, enabled: Boolean = true, ) { - ZoomLayout(modifier = modifier) { - Row( - modifier = Modifier.fillMaxSize(), + var offset by remember { mutableStateOf(Offset.Zero) } + var zoom by remember { mutableStateOf(1f) } + + Row(modifier = modifier) { + // Line Numbers + ZoomLayout( + modifier = Modifier.zIndex(1f), + offset = offset.copy(x = 0f), + zoom = zoom, + onOffsetChanged = {}, + onZoomChanged = {}, ) { LineNumbers( text = text.text, + textStyle = textStyle, textColor = colors.lineNumberTextColor().value, backgroundColor = colors.lineNumberBackgroundColor().value, ) + } + +// val configuration = LocalConfiguration.current + // Text Editor + ZoomLayout( + modifier = Modifier.zIndex(0f), + offset = offset, + zoom = zoom, + onOffsetChanged = { +// val newOffset = Offset( +// x = (offset + it).x.coerceIn(0f, (size.width.toFloat() - (configuration.screenWidthDp.dp.toPx() / newScale)).coerceAtLeast(0f)), +// y = (offset + it).y.coerceIn(0f, (size.height.toFloat() - (configuration.screenHeightDp.dp.toPx() / newScale)).coerceAtLeast(0f)), +// ) + + val newOffset = offset + (it / zoom) + offset = newOffset.copy( + x = newOffset.x.coerceAtLeast(0f), + y = newOffset.y.coerceAtLeast(0f) + ) + }, + onZoomChanged = { zoom *= it }, + ) { KodeTextField( modifier = Modifier .wrapContentSize( @@ -80,6 +123,7 @@ fun KodeEditor( colorScheme = colorScheme, onValueChange = onValueChange, colors = colors.textFieldColors(enabled = enabled).value, + textStyle = textStyle, ) } } diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt index 73e38b4..5567cc1 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt @@ -3,6 +3,7 @@ package de.markusressel.kodeeditor.library.compose import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material.LocalTextStyle import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -10,6 +11,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -17,7 +19,7 @@ import androidx.compose.ui.unit.dp @Preview @Composable -fun LineNumbersPreview() { +private fun LineNumbersPreview() { val text = (1..10).joinToString(separator = "\n", prefix = "Line: ") LineNumbers( text = text, @@ -29,6 +31,7 @@ fun LineNumbersPreview() { @Composable fun LineNumbers( text: String, + textStyle: TextStyle = LocalTextStyle.current, backgroundColor: Color, textColor: Color = Color.Unspecified, ) { @@ -44,6 +47,7 @@ fun LineNumbers( .background(color = backgroundColor) .padding(start = 4.dp, end = 4.dp), text = lineNumbers, + fontSize = textStyle.fontSize, color = textColor, textAlign = TextAlign.End, ) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt index 1e77646..3fef91c 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt @@ -5,24 +5,29 @@ import androidx.compose.foundation.gestures.detectTransformGestures import androidx.compose.foundation.layout.* import androidx.compose.material.Surface import androidx.compose.runtime.* -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @Preview @Composable -fun ZoomLayoutPreview() { +private fun ZoomLayoutPreview() { + var offset by remember { mutableStateOf(Offset.Zero) } + var zoom by remember { mutableStateOf(1f) } + ZoomLayout( modifier = Modifier .padding(16.dp) - .background(Color.White) + .background(Color.White), + zoom = zoom, + offset = offset, + onOffsetChanged = { offset = it }, + onZoomChanged = { zoom = it }, ) { Column(modifier = Modifier) { for (i in 1..10) { @@ -45,55 +50,46 @@ fun ZoomLayoutPreview() { @Composable fun ZoomLayout( modifier: Modifier = Modifier, + zoom: Float = 1f, + offset: Offset = Offset.Zero, + onOffsetChanged: (Offset) -> Unit, + onZoomChanged: (Float) -> Unit, content: @Composable () -> Unit, ) { Box( - modifier = modifier.wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ) - ) { - val configuration = LocalConfiguration.current - - var offset by remember { mutableStateOf(Offset.Zero) } - var zoom by remember { mutableStateOf(1f) } - - Box( - modifier = Modifier - .wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ) - .pointerInput(Unit) { - detectTransformGestures { centroid, pan, gestureZoom, gestureRotate -> + modifier = Modifier + .pointerInput(Unit) { + detectTransformGestures { centroid, pan, gestureZoom, gestureRotate -> - val oldScale = zoom - val newScale = zoom * gestureZoom + val oldScale = zoom + val newScale = zoom * gestureZoom - // For natural zooming and rotating, the centroid of the gesture should - // be the fixed point where zooming and rotating occurs. - // We compute where the centroid was (in the pre-transformed coordinate - // space), and then compute where it will be after this delta. - // We then compute what the new offset should be to keep the centroid - // visually stationary for rotating and zooming, and also apply the pan. - offset = (offset + centroid / oldScale) - (centroid / newScale + pan / oldScale) + // For natural zooming and rotating, the centroid of the gesture should + // be the fixed point where zooming and rotating occurs. + // We compute where the centroid was (in the pre-transformed coordinate + // space), and then compute where it will be after this delta. + // We then compute what the new offset should be to keep the centroid + // visually stationary for rotating and zooming, and also apply the pan. + val tOffset = (offset + centroid / oldScale) - (centroid / newScale + pan / oldScale) - offset = Offset( - x = offset.x.coerceIn(0f, (size.width.toFloat() - (configuration.screenWidthDp.dp.toPx() / newScale)).coerceAtLeast(0f)), - y = offset.y.coerceIn(0f, (size.height.toFloat() - (configuration.screenHeightDp.dp.toPx() / newScale)).coerceAtLeast(0f)), - ) + if (offset != tOffset) { + onOffsetChanged(tOffset) + } - zoom = (newScale).coerceIn(0.1f, 5f) + val newZoom = (newScale).coerceIn(0.01f, 10f) + if (zoom != newZoom) { + onZoomChanged(newZoom) } } - .graphicsLayer( - transformOrigin = TransformOrigin(0f, 0f), - scaleX = zoom, scaleY = zoom, - translationX = -offset.x * zoom, - translationY = -offset.y * zoom, - ), - ) { - content() - } + } + .graphicsLayer( + transformOrigin = TransformOrigin(0f, 0f), + scaleX = zoom, scaleY = zoom, + translationX = -offset.x * zoom, + translationY = -offset.y * zoom, + ) + .then(modifier), + ) { + content() } } \ No newline at end of file From 089121f080c8571c16d3c1c062fe9726bc0d3e63 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 16 Dec 2022 02:45:13 +0100 Subject: [PATCH 16/62] update versions --- app/build.gradle | 10 +++++----- build.gradle | 4 ++-- library/build.gradle | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a74ff8f..f74b9b9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -63,21 +63,21 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.5.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.google.android.material:material:1.7.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' - implementation 'androidx.activity:activity-compose:1.6.0' + implementation 'androidx.activity:activity-compose:1.6.1' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" + implementation "androidx.compose.ui:ui-tooling-preview:1.3.2" def fuelVersion = "2.3.1" implementation "com.github.kittinunf.fuel:fuel:$fuelVersion" implementation "com.github.kittinunf.fuel:fuel-android:$fuelVersion" testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.4' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9490345..e8d6c98 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.7.20' ext.dokka_version = '1.6.21' ext { @@ -29,7 +29,7 @@ buildscript { timberKtVersion = "1.5.1" compose_compiler_version = '1.3.1' - compose_version = '1.3.0-beta03' + compose_version = '1.4.0-alpha03' } repositories { diff --git a/library/build.gradle b/library/build.gradle index 08a871c..4e30064 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -42,12 +42,12 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'androidx.annotation:annotation:1.5.0' - implementation "androidx.compose.ui:ui:1.2.1" - implementation "androidx.compose.material:material:1.2.1" - implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" + implementation "androidx.compose.ui:ui:1.3.2" + implementation "androidx.compose.material:material:1.3.1" + implementation "androidx.compose.ui:ui-tooling-preview:1.3.2" - debugImplementation "androidx.compose.ui:ui-tooling:1.2.1" - implementation "androidx.compose.ui:ui-tooling-preview:1.2.1" + debugImplementation "androidx.compose.ui:ui-tooling:1.3.2" + implementation "androidx.compose.ui:ui-tooling-preview:1.3.2" // RxFlow implementation "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBindingVersion" @@ -57,7 +57,7 @@ dependencies { // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") { - changing = true + changing = false } debugImplementation "com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion" From bbc00def321c25c0feb97b5521ff95914df760d5 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 16 Dec 2022 02:46:52 +0100 Subject: [PATCH 17/62] update versions --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e8d6c98..06eb22f 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ buildscript { flowBindingVersion = "1.0.0" timberKtVersion = "1.5.1" - compose_compiler_version = '1.3.1' + compose_compiler_version = '1.3.2' compose_version = '1.4.0-alpha03' } From bf6f50031dc37e13fef38d9e36ce6dfef3f0afa3 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 16 Dec 2022 02:53:45 +0100 Subject: [PATCH 18/62] added jitpack config --- .jitpack.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .jitpack.yml diff --git a/.jitpack.yml b/.jitpack.yml new file mode 100644 index 0000000..f78f664 --- /dev/null +++ b/.jitpack.yml @@ -0,0 +1 @@ +jdk: openjdk11 \ No newline at end of file From 356d642c7808c9d3a3729442cc95578f5540fff8 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 16 Dec 2022 03:05:22 +0100 Subject: [PATCH 19/62] remove debug dependency to fix release build --- library/build.gradle | 6 ++-- .../kodeeditor/library/compose/KodeEditor.kt | 34 ++++++++++++++++--- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 4e30064..b8e6661 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -60,8 +60,6 @@ dependencies { changing = false } - debugImplementation "com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" @@ -69,8 +67,8 @@ dependencies { api 'com.otaliastudios:zoomlayout:1.9.0' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.4' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' } configurations.all { diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 99543c0..7bb2bd4 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue @@ -15,10 +16,35 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import de.markusressel.kodehighlighter.core.LanguageRuleBook +import de.markusressel.kodehighlighter.core.StyleFactory import de.markusressel.kodehighlighter.core.colorscheme.ColorScheme +import de.markusressel.kodehighlighter.core.rule.LanguageRule +import de.markusressel.kodehighlighter.core.rule.RuleHelper +import de.markusressel.kodehighlighter.core.rule.RuleMatch import de.markusressel.kodehighlighter.core.ui.KodeTextField -import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook -import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle + +data class DummyData( + val headingRule: LanguageRule = object : LanguageRule { + override fun findMatches(text: CharSequence): List { + val PATTERN = "^\\s{0,3}#{1,6} .+".toRegex(RegexOption.MULTILINE) + return RuleHelper.findRegexMatches(text, PATTERN) + } + }, + + val dummyRuleBook: LanguageRuleBook = object : LanguageRuleBook { + override fun getRules() = listOf( + headingRule + ) + }, + + val colorScheme: ColorScheme = object : ColorScheme { + override fun getStyles(type: LanguageRule): Set> { + return setOf { SpanStyle(Color(0xFFFF6D00)) } + } + } +) + +private val dummyData = DummyData() @Preview @Composable @@ -34,10 +60,10 @@ private fun KodeEditorPreview() { } val languageRuleBook by remember { - mutableStateOf(MarkdownRuleBook()) + mutableStateOf(dummyData.dummyRuleBook) } val colorScheme by remember { - mutableStateOf(DarkBackgroundColorSchemeWithSpanStyle()) + mutableStateOf(dummyData.colorScheme) } KodeEditor( From f8dc47d7c3cce2f7aebad3634ad596ed809da8cd Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 22 Dec 2022 00:21:00 +0100 Subject: [PATCH 20/62] added readOnly parameter --- .../de/markusressel/kodeeditor/library/compose/KodeEditor.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 7bb2bd4..2c7ad5a 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -95,6 +95,7 @@ fun KodeEditor( colors: KodeEditorColors = KodeEditorDefaults.editorColors(), textStyle: TextStyle = LocalTextStyle.current, enabled: Boolean = true, + readOnly: Boolean = enabled, ) { var offset by remember { mutableStateOf(Offset.Zero) } var zoom by remember { mutableStateOf(1f) } @@ -150,6 +151,8 @@ fun KodeEditor( onValueChange = onValueChange, colors = colors.textFieldColors(enabled = enabled).value, textStyle = textStyle, + enabled = enabled, + readOnly = readOnly, ) } } From bc45491c7746fdff908735f38d33208a3ddac5f2 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 22 Dec 2022 00:21:25 +0100 Subject: [PATCH 21/62] added readOnly parameter --- .../de/markusressel/kodeeditor/library/compose/KodeEditor.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 2c7ad5a..6fe3365 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -84,6 +84,7 @@ private fun KodeEditorPreview() { * @param colors the color scheme to use for highlighting * @param textStyle the text style used for the editor text * @param enabled whether the editor is enabled + * @param readOnly whether the contents of the editor can be changed by the user */ @Composable fun KodeEditor( From d43af227db8d58539b49eefdcb9c7b714293a50a Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Wed, 4 Jan 2023 19:18:02 +0100 Subject: [PATCH 22/62] fix clipping, fix line numbers --- .../kodeeditor/library/compose/KodeEditor.kt | 32 +++++++++++++------ .../kodeeditor/library/compose/LineNumbers.kt | 24 +++++++------- .../kodeeditor/library/compose/ZoomLayout.kt | 6 ++-- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 7bb2bd4..e84dfc0 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -1,14 +1,15 @@ package de.markusressel.kodeeditor.library.compose -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.layout.* import androidx.compose.material.LocalTextStyle import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.TransformOrigin +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue @@ -80,6 +81,7 @@ private fun KodeEditorPreview() { * @param modifier compose modifiers * @param text the current text of the editor * @param languageRuleBook the language rule book to use for highlighting + * @param colorScheme the color scheme to apply * @param onValueChange callback for changes to the text and/or cursor selection * @param colors the color scheme to use for highlighting * @param textStyle the text style used for the editor text @@ -99,16 +101,28 @@ fun KodeEditor( var offset by remember { mutableStateOf(Offset.Zero) } var zoom by remember { mutableStateOf(1f) } - Row(modifier = modifier) { + Row(modifier = Modifier + .clipToBounds() + .then(modifier) + ) { // Line Numbers - ZoomLayout( + Box( modifier = Modifier.zIndex(1f), - offset = offset.copy(x = 0f), - zoom = zoom, - onOffsetChanged = {}, - onZoomChanged = {}, ) { LineNumbers( + modifier = Modifier + .height(IntrinsicSize.Max) + .wrapContentWidth() + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + .graphicsLayer( + transformOrigin = TransformOrigin(0f, 0f), + scaleX = zoom, scaleY = zoom, + translationX = 0f, + translationY = -offset.y * zoom, + ), text = text.text, textStyle = textStyle, textColor = colors.lineNumberTextColor().value, diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt index 5567cc1..8835e72 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt @@ -1,8 +1,8 @@ package de.markusressel.kodeeditor.library.compose import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.material.LocalTextStyle import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -30,6 +30,7 @@ private fun LineNumbersPreview() { @Composable fun LineNumbers( + modifier: Modifier = Modifier, text: String, textStyle: TextStyle = LocalTextStyle.current, backgroundColor: Color, @@ -41,15 +42,16 @@ fun LineNumbers( mutableStateOf(lineText) } - Text( - modifier = Modifier - .wrapContentWidth() - .background(color = backgroundColor) - .padding(start = 4.dp, end = 4.dp), - text = lineNumbers, - fontSize = textStyle.fontSize, - color = textColor, - textAlign = TextAlign.End, - ) + Box(modifier = modifier) { + Text( + modifier = Modifier + .background(color = backgroundColor) + .padding(start = 4.dp, end = 4.dp), + text = lineNumbers, + fontSize = textStyle.fontSize, + color = textColor, + textAlign = TextAlign.End, + ) + } } diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt index 3fef91c..ba3314c 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt @@ -18,7 +18,7 @@ import androidx.compose.ui.unit.dp @Composable private fun ZoomLayoutPreview() { var offset by remember { mutableStateOf(Offset.Zero) } - var zoom by remember { mutableStateOf(1f) } + var zoom by remember { mutableStateOf(2f) } ZoomLayout( modifier = Modifier @@ -51,6 +51,8 @@ private fun ZoomLayoutPreview() { fun ZoomLayout( modifier: Modifier = Modifier, zoom: Float = 1f, + minZoom: Float = 0.01f, + maxZoom: Float = 10f, offset: Offset = Offset.Zero, onOffsetChanged: (Offset) -> Unit, onZoomChanged: (Float) -> Unit, @@ -76,7 +78,7 @@ fun ZoomLayout( onOffsetChanged(tOffset) } - val newZoom = (newScale).coerceIn(0.01f, 10f) + val newZoom = (newScale).coerceIn(minZoom, maxZoom) if (zoom != newZoom) { onZoomChanged(newZoom) } From b550ee305fe58d5cf8729f51244a6de5713adeaa Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Wed, 4 Jan 2023 19:33:08 +0100 Subject: [PATCH 23/62] improved padding --- .../kodeeditor/library/compose/KodeEditor.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 4bd3011..7338fff 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -10,6 +10,8 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue @@ -101,12 +103,16 @@ fun KodeEditor( readOnly: Boolean = enabled, ) { var offset by remember { mutableStateOf(Offset.Zero) } - var zoom by remember { mutableStateOf(1f) } + var zoom by remember { mutableStateOf(4f) } Row(modifier = Modifier .clipToBounds() .then(modifier) ) { + var lineNumberWidth by remember { + mutableStateOf(0) + } + // Line Numbers Box( modifier = Modifier.zIndex(1f), @@ -119,6 +125,9 @@ fun KodeEditor( align = Alignment.TopStart, unbounded = true ) + .onGloballyPositioned { + lineNumberWidth = it.size.width + } .graphicsLayer( transformOrigin = TransformOrigin(0f, 0f), scaleX = zoom, scaleY = zoom, @@ -159,7 +168,10 @@ fun KodeEditor( align = Alignment.TopStart, unbounded = true ) - .padding(horizontal = 4.dp), + .padding( + start = LocalDensity.current.run { lineNumberWidth.toDp() } + 4.dp, + end = 4.dp + ), value = text, languageRuleBook = languageRuleBook, colorScheme = colorScheme, From 4b00a4dbc16d39952ac2be70f5e41351bb1b567f Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Wed, 4 Jan 2023 19:37:12 +0100 Subject: [PATCH 24/62] reset default zoom --- .../de/markusressel/kodeeditor/library/compose/KodeEditor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 7338fff..61463b9 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -103,7 +103,7 @@ fun KodeEditor( readOnly: Boolean = enabled, ) { var offset by remember { mutableStateOf(Offset.Zero) } - var zoom by remember { mutableStateOf(4f) } + var zoom by remember { mutableStateOf(1f) } Row(modifier = Modifier .clipToBounds() From c8d8c1f4c3242c3c74dbaaced6f77bd1c9282519 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 8 Jan 2023 20:19:05 +0100 Subject: [PATCH 25/62] fix "readOnly" default state, fix background not beeing applied to the whole ui element --- library/build.gradle | 6 +++--- .../kodeeditor/library/compose/KodeEditor.kt | 4 +++- .../kodeeditor/library/compose/KodeEditorColors.kt | 14 ++++++++++++++ .../kodeeditor/library/compose/ZoomLayout.kt | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index b8e6661..63726f5 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -57,7 +57,7 @@ dependencies { // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") { - changing = false + changing = true } implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" @@ -67,8 +67,8 @@ dependencies { api 'com.otaliastudios:zoomlayout:1.9.0' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.4' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } configurations.all { diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 61463b9..3da3d8c 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -1,5 +1,6 @@ package de.markusressel.kodeeditor.library.compose +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.LocalTextStyle import androidx.compose.runtime.* @@ -100,7 +101,7 @@ fun KodeEditor( colors: KodeEditorColors = KodeEditorDefaults.editorColors(), textStyle: TextStyle = LocalTextStyle.current, enabled: Boolean = true, - readOnly: Boolean = enabled, + readOnly: Boolean = enabled.not(), ) { var offset by remember { mutableStateOf(Offset.Zero) } var zoom by remember { mutableStateOf(1f) } @@ -168,6 +169,7 @@ fun KodeEditor( align = Alignment.TopStart, unbounded = true ) + .background(colors.textFieldBackgroundColor().value) .padding( start = LocalDensity.current.run { lineNumberWidth.toDp() } + 4.dp, end = 4.dp diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt index b456231..69c5a87 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt @@ -25,6 +25,12 @@ interface KodeEditorColors { @Composable fun textFieldColors(enabled: Boolean): State + /** + * Represents the color used for the background of the editor text. + */ + @Composable + fun textFieldBackgroundColor(): State + /** * Represents the color used for line numbers text. */ @@ -53,11 +59,13 @@ object KodeEditorDefaults { @Composable fun editorColors( textFieldColors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), + textFieldBackgroundColor: Color = MaterialTheme.colors.surface, lineNumberTextColor: Color = Color.Unspecified, lineNumberBackgroundColor: Color = MaterialTheme.colors.onSurface, ): KodeEditorColors = DefaultKodeEditorColors( textFieldColors = textFieldColors, + textFieldBackgroundColor = textFieldBackgroundColor, lineNumberTextColor = lineNumberTextColor, lineNumberBackgroundColor = lineNumberBackgroundColor, ) @@ -66,6 +74,7 @@ object KodeEditorDefaults { private data class DefaultKodeEditorColors( private val textFieldColors: KodeTextFieldColors, + private val textFieldBackgroundColor: Color, private val lineNumberTextColor: Color, private val lineNumberBackgroundColor: Color, ) : KodeEditorColors { @@ -75,6 +84,11 @@ private data class DefaultKodeEditorColors( return rememberUpdatedState(textFieldColors) } + @Composable + override fun textFieldBackgroundColor(): State { + return rememberUpdatedState(textFieldBackgroundColor) + } + @Composable override fun lineNumberTextColor(): State { return rememberUpdatedState(lineNumberTextColor) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt index ba3314c..77a1130 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/ZoomLayout.kt @@ -56,7 +56,7 @@ fun ZoomLayout( offset: Offset = Offset.Zero, onOffsetChanged: (Offset) -> Unit, onZoomChanged: (Float) -> Unit, - content: @Composable () -> Unit, + content: @Composable BoxScope.() -> Unit, ) { Box( modifier = Modifier From 36783b9bf8b9186d7785e663555f5df7cdaadf67 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 8 Jan 2023 20:28:39 +0100 Subject: [PATCH 26/62] fix default colors, fix padding when zooming --- .../kodeeditor/library/compose/KodeEditor.kt | 18 +++++++++++++++++- .../library/compose/KodeEditorColors.kt | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 3da3d8c..6d2972d 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -57,6 +57,20 @@ private fun KodeEditorPreview() { val initialText = """ # Hello World Code: `readResourceFileAsText(R.raw.sample_text)` + + ## Secondary headline + + This is a listing: + + * 1 + * 2 + * 3 + + # Code Block + + ``` + This is a code block. + ``` """.trimIndent() mutableStateOf(TextFieldValue( text = initialText @@ -163,6 +177,8 @@ fun KodeEditor( }, onZoomChanged = { zoom *= it }, ) { + val additionPaddingBecauseOfZoom = (LocalDensity.current.run { lineNumberWidth.toDp() }) - (LocalDensity.current.run { lineNumberWidth.toDp() } / zoom) + KodeTextField( modifier = Modifier .wrapContentSize( @@ -171,7 +187,7 @@ fun KodeEditor( ) .background(colors.textFieldBackgroundColor().value) .padding( - start = LocalDensity.current.run { lineNumberWidth.toDp() } + 4.dp, + start = additionPaddingBecauseOfZoom + 4.dp, end = 4.dp ), value = text, diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt index 69c5a87..67838e1 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt @@ -61,7 +61,7 @@ object KodeEditorDefaults { textFieldColors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), textFieldBackgroundColor: Color = MaterialTheme.colors.surface, lineNumberTextColor: Color = Color.Unspecified, - lineNumberBackgroundColor: Color = MaterialTheme.colors.onSurface, + lineNumberBackgroundColor: Color = MaterialTheme.colors.surface, ): KodeEditorColors = DefaultKodeEditorColors( textFieldColors = textFieldColors, From a89b0b06a88b7600c26504ca2c4525e2a701eca4 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 8 Jan 2023 21:21:41 +0100 Subject: [PATCH 27/62] better layout, allow zoom <= 1 again --- .../kodeeditor/library/compose/KodeEditor.kt | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 6d2972d..cb7300e 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -120,47 +120,53 @@ fun KodeEditor( var offset by remember { mutableStateOf(Offset.Zero) } var zoom by remember { mutableStateOf(1f) } - Row(modifier = Modifier + Box(modifier = Modifier .clipToBounds() .then(modifier) ) { var lineNumberWidth by remember { mutableStateOf(0) } - - // Line Numbers - Box( - modifier = Modifier.zIndex(1f), - ) { - LineNumbers( - modifier = Modifier - .height(IntrinsicSize.Max) - .wrapContentWidth() - .wrapContentSize( - align = Alignment.TopStart, - unbounded = true - ) - .onGloballyPositioned { - lineNumberWidth = it.size.width - } - .graphicsLayer( - transformOrigin = TransformOrigin(0f, 0f), - scaleX = zoom, scaleY = zoom, - translationX = 0f, - translationY = -offset.y * zoom, - ), - text = text.text, - textStyle = textStyle, - textColor = colors.lineNumberTextColor().value, - backgroundColor = colors.lineNumberBackgroundColor().value, - ) - } +// Line Numbers + LineNumbers( + modifier = Modifier + .zIndex(1f) + .height(IntrinsicSize.Max) + .wrapContentWidth() + .wrapContentSize( + align = Alignment.TopStart, + unbounded = true + ) + .onGloballyPositioned { + lineNumberWidth = it.size.width + } + .graphicsLayer( + transformOrigin = TransformOrigin(0f, 0f), + scaleX = zoom, scaleY = zoom, + translationX = 0f, + translationY = -offset.y * zoom, + ), + text = text.text, + textStyle = textStyle, + textColor = colors.lineNumberTextColor().value, + backgroundColor = colors.lineNumberBackgroundColor().value, + ) // val configuration = LocalConfiguration.current + + val computedPadding = LocalDensity.current.run { + //(lineNumberWidth + (lineNumberWidth - (lineNumberWidth / zoom))).coerceAtLeast(0f).toDp() + (lineNumberWidth).coerceAtLeast(0).toDp() + } + // Text Editor ZoomLayout( - modifier = Modifier.zIndex(0f), + modifier = Modifier + .zIndex(0f) + .padding( + start = computedPadding, + ), offset = offset, zoom = zoom, onOffsetChanged = { @@ -175,19 +181,20 @@ fun KodeEditor( y = newOffset.y.coerceAtLeast(0f) ) }, - onZoomChanged = { zoom *= it }, + onZoomChanged = { + zoom *= it + }, ) { - val additionPaddingBecauseOfZoom = (LocalDensity.current.run { lineNumberWidth.toDp() }) - (LocalDensity.current.run { lineNumberWidth.toDp() } / zoom) - KodeTextField( modifier = Modifier + .align(Alignment.TopStart) .wrapContentSize( align = Alignment.TopStart, unbounded = true ) .background(colors.textFieldBackgroundColor().value) .padding( - start = additionPaddingBecauseOfZoom + 4.dp, + start = 4.dp, end = 4.dp ), value = text, From a88dd37b9c2d6626debbf465672ad1a98015e8ff Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 8 Jan 2023 21:23:53 +0100 Subject: [PATCH 28/62] removed unnecessary comments --- .../de/markusressel/kodeeditor/library/compose/KodeEditor.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index cb7300e..5b94699 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -127,7 +127,6 @@ fun KodeEditor( var lineNumberWidth by remember { mutableStateOf(0) } -// Line Numbers LineNumbers( modifier = Modifier .zIndex(1f) @@ -152,11 +151,7 @@ fun KodeEditor( backgroundColor = colors.lineNumberBackgroundColor().value, ) -// val configuration = LocalConfiguration.current - - val computedPadding = LocalDensity.current.run { - //(lineNumberWidth + (lineNumberWidth - (lineNumberWidth / zoom))).coerceAtLeast(0f).toDp() (lineNumberWidth).coerceAtLeast(0).toDp() } From 3b4cafd72b71c70a403601c4ce5f6dac95bc885a Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 8 Jan 2023 21:43:21 +0100 Subject: [PATCH 29/62] demo app improvements --- .../kodeeditor/ComposeMainActivity.kt | 69 +++++++++++++------ .../library/compose/KodeEditorColors.kt | 2 +- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 997dac1..2e0a08c 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -4,18 +4,21 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.RawRes -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme 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.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import de.markusressel.kodeeditor.library.compose.KodeEditor import de.markusressel.kodeeditor.library.compose.KodeEditorDefaults @@ -31,16 +34,14 @@ class ComposeMainActivity : ComponentActivity() { var fontSize by remember { mutableStateOf(14) } - Column { - Row { - Button(onClick = { fontSize++ }) { - Text(text = "+") - } - - Button(onClick = { fontSize-- }) { - Text(text = "-") - } - } + Column( + modifier = Modifier.background(MaterialTheme.colors.background), + ) { + KodeEditorConfigurationMenu( + fontSize = fontSize, + onIncreaseFontSize = { fontSize++ }, + onDecreaseFontSize = { fontSize-- }, + ) var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { val initialText = readResourceFileAsText(R.raw.sample_text) @@ -48,22 +49,50 @@ class ComposeMainActivity : ComponentActivity() { } KodeEditor( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .border(BorderStroke(1.dp, MaterialTheme.colors.primary)), languageRuleBook = MarkdownRuleBook(), colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), text = text, onValueChange = { text = it }, - textStyle = TextStyle(fontSize = fontSize.sp), - colors = KodeEditorDefaults.editorColors( - lineNumberTextColor = Color.Black, - lineNumberBackgroundColor = Color.White, - ) + textStyle = TextStyle(fontSize = fontSize.sp).copy( + color = MaterialTheme.colors.onSurface, + ), + colors = KodeEditorDefaults.editorColors() ) } } } } + @Composable + private fun KodeEditorConfigurationMenu( + fontSize: Int, + onIncreaseFontSize: () -> Unit, + onDecreaseFontSize: () -> Unit, + ) { + Row( + modifier = Modifier.padding(4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + modifier = Modifier.weight(1f), + text = "Font Size: $fontSize" + ) + + Button(onClick = onIncreaseFontSize) { + Text(text = "+") + } + + Spacer(modifier = Modifier.size(4.dp)) + + Button(onClick = onDecreaseFontSize) { + Text(text = "-") + } + } + } + private fun readResourceFileAsText(@RawRes resourceId: Int) = resources.openRawResource(resourceId).bufferedReader().readText() diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt index 67838e1..ea869cf 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditorColors.kt @@ -60,7 +60,7 @@ object KodeEditorDefaults { fun editorColors( textFieldColors: KodeTextFieldColors = KodeTextFieldDefaults.textFieldColors(), textFieldBackgroundColor: Color = MaterialTheme.colors.surface, - lineNumberTextColor: Color = Color.Unspecified, + lineNumberTextColor: Color = MaterialTheme.colors.onSurface, lineNumberBackgroundColor: Color = MaterialTheme.colors.surface, ): KodeEditorColors = DefaultKodeEditorColors( From 57767394ef16f310b20ef71f03d8d913e4c66569 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 8 Jan 2023 23:22:52 +0100 Subject: [PATCH 30/62] demo app improvements --- .../kodeeditor/ComposeMainActivity.kt | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 2e0a08c..9f59457 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -31,16 +31,17 @@ class ComposeMainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContent { KodeEditorTheme { - var fontSize by remember { + var currentFontSize by remember { mutableStateOf(14) } + Column( modifier = Modifier.background(MaterialTheme.colors.background), ) { KodeEditorConfigurationMenu( - fontSize = fontSize, - onIncreaseFontSize = { fontSize++ }, - onDecreaseFontSize = { fontSize-- }, + currentFontSize = currentFontSize, + onIncreaseFontSize = { currentFontSize++ }, + onDecreaseFontSize = { currentFontSize-- }, ) var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { @@ -56,7 +57,7 @@ class ComposeMainActivity : ComponentActivity() { colorScheme = DarkBackgroundColorSchemeWithSpanStyle(), text = text, onValueChange = { text = it }, - textStyle = TextStyle(fontSize = fontSize.sp).copy( + textStyle = TextStyle(fontSize = currentFontSize.sp).copy( color = MaterialTheme.colors.onSurface, ), colors = KodeEditorDefaults.editorColors() @@ -68,27 +69,31 @@ class ComposeMainActivity : ComponentActivity() { @Composable private fun KodeEditorConfigurationMenu( - fontSize: Int, + currentFontSize: Int, onIncreaseFontSize: () -> Unit, onDecreaseFontSize: () -> Unit, ) { - Row( + Column( modifier = Modifier.padding(4.dp), - verticalAlignment = Alignment.CenterVertically, + verticalArrangement = Arrangement.spacedBy(4.dp) ) { - Text( - modifier = Modifier.weight(1f), - text = "Font Size: $fontSize" - ) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + modifier = Modifier.weight(1f), + text = "Font Size: $currentFontSize" + ) - Button(onClick = onIncreaseFontSize) { - Text(text = "+") - } + Button(onClick = onIncreaseFontSize) { + Text(text = "+") + } - Spacer(modifier = Modifier.size(4.dp)) + Spacer(modifier = Modifier.size(4.dp)) - Button(onClick = onDecreaseFontSize) { - Text(text = "-") + Button(onClick = onDecreaseFontSize) { + Text(text = "-") + } } } } From 463ce37198ecde2127f7eff7317b187b19e57b48 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 9 Jan 2023 01:27:05 +0100 Subject: [PATCH 31/62] theme fixes --- .../markusressel/kodeeditor/ComposeMainActivity.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 9f59457..7f07eea 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -82,17 +82,24 @@ class ComposeMainActivity : ComponentActivity() { ) { Text( modifier = Modifier.weight(1f), - text = "Font Size: $currentFontSize" + text = "Font Size: $currentFontSize", + color = MaterialTheme.colors.onSurface, ) Button(onClick = onIncreaseFontSize) { - Text(text = "+") + Text( + text = "+", + color = MaterialTheme.colors.onPrimary, + ) } Spacer(modifier = Modifier.size(4.dp)) Button(onClick = onDecreaseFontSize) { - Text(text = "-") + Text( + text = "-", + color = MaterialTheme.colors.onPrimary, + ) } } } From f19a7741397bcee8dcb0f39d18d4d38ea319a780 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Wed, 11 Jan 2023 00:08:20 +0100 Subject: [PATCH 32/62] fix size issues, added shorter text sample --- .../de/markusressel/kodeeditor/ComposeMainActivity.kt | 3 ++- app/src/main/res/raw/short_sample | 2 ++ .../kodeeditor/library/compose/KodeEditor.kt | 10 ++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/raw/short_sample diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 7f07eea..2bb2d75 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -45,7 +45,8 @@ class ComposeMainActivity : ComponentActivity() { ) var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { - val initialText = readResourceFileAsText(R.raw.sample_text) + val initialText = readResourceFileAsText(R.raw.short_sample) +// val initialText = readResourceFileAsText(R.raw.sample_text) mutableStateOf(TextFieldValue(initialText)) } diff --git a/app/src/main/res/raw/short_sample b/app/src/main/res/raw/short_sample new file mode 100644 index 0000000..c605b18 --- /dev/null +++ b/app/src/main/res/raw/short_sample @@ -0,0 +1,2 @@ +# KodeEditor +A simple code editor with syntax highlighting and pinch to zoom diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 5b94699..881827d 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -1,7 +1,9 @@ package de.markusressel.kodeeditor.library.compose import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material.LocalTextStyle import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -130,8 +132,6 @@ fun KodeEditor( LineNumbers( modifier = Modifier .zIndex(1f) - .height(IntrinsicSize.Max) - .wrapContentWidth() .wrapContentSize( align = Alignment.TopStart, unbounded = true @@ -161,7 +161,8 @@ fun KodeEditor( .zIndex(0f) .padding( start = computedPadding, - ), + ) + .matchParentSize(), offset = offset, zoom = zoom, onOffsetChanged = { @@ -187,6 +188,7 @@ fun KodeEditor( align = Alignment.TopStart, unbounded = true ) + .matchParentSize() .background(colors.textFieldBackgroundColor().value) .padding( start = 4.dp, From 52cc4c941703e372aa8ce4402581921149611f57 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 14 May 2023 01:18:55 +0200 Subject: [PATCH 33/62] upgrades --- .github/workflows/build.yml | 6 +++--- app/build.gradle | 20 ++++++++++---------- build.gradle | 10 +++++----- gradle.properties | 5 ++++- gradle/wrapper/gradle-wrapper.properties | 2 +- library/build.gradle | 24 ++++++++++++------------ 6 files changed, 35 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f1c928..921fb87 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Perform base checks run: ./gradlew app:assembleDebug library:sourcesJar library:dokkaJar --stacktrace ANDROID_UNIT_TESTS: @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Execute unit tests run: ./gradlew library:testDebugUnitTest --stacktrace ANDROID_BUILD_APK: @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Setup custom keystore file run: | diff --git a/app/build.gradle b/app/build.gradle index f74b9b9..62d452a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,8 +35,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } packagingOptions { @@ -46,7 +46,7 @@ android { } } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = JavaVersion.VERSION_17.toString() } composeOptions { kotlinCompilerExtensionVersion compose_compiler_version @@ -62,22 +62,22 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.5.1' - implementation 'com.google.android.material:material:1.7.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.9.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' - implementation 'androidx.activity:activity-compose:1.6.1' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1' + implementation 'androidx.activity:activity-compose:1.7.1' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:1.3.2" + implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" def fuelVersion = "2.3.1" implementation "com.github.kittinunf.fuel:fuel:$fuelVersion" implementation "com.github.kittinunf.fuel:fuel-android:$fuelVersion" testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.4' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 06eb22f..c7cf2f1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.7.20' + ext.kotlin_version = '1.8.21' ext.dokka_version = '1.6.21' ext { group = 'com.github.markusressel' - gradle_plugin_version = '7.3.0' + gradle_plugin_version = '8.0.0' minSdkVersion = 21 versionName = "4.0.1" @@ -28,7 +28,7 @@ buildscript { flowBindingVersion = "1.0.0" timberKtVersion = "1.5.1" - compose_compiler_version = '1.3.2' + compose_compiler_version = '1.4.7' compose_version = '1.4.0-alpha03' } @@ -58,11 +58,11 @@ apply plugin: 'kotlin' compileKotlin { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = JavaVersion.VERSION_1_8.toString() } } compileTestKotlin { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = JavaVersion.VERSION_1_8.toString() } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index dc251f5..671783c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,7 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e9bf75f..de840f0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip diff --git a/library/build.gradle b/library/build.gradle index 63726f5..ac7d614 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -21,8 +21,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } buildFeatures { @@ -39,21 +39,21 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' - implementation 'androidx.appcompat:appcompat:1.5.1' - implementation 'androidx.annotation:annotation:1.5.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.annotation:annotation:1.6.0' - implementation "androidx.compose.ui:ui:1.3.2" - implementation "androidx.compose.material:material:1.3.1" - implementation "androidx.compose.ui:ui-tooling-preview:1.3.2" + implementation "androidx.compose.ui:ui:1.4.3" + implementation "androidx.compose.material:material:1.4.3" + implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" - debugImplementation "androidx.compose.ui:ui-tooling:1.3.2" - implementation "androidx.compose.ui:ui-tooling-preview:1.3.2" + debugImplementation "androidx.compose.ui:ui-tooling:1.4.3" + implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" // RxFlow implementation "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBindingVersion" // Lifecycle - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1" // Syntax Highlighting api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") { @@ -78,11 +78,11 @@ configurations.all { // build a jar with source files task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs - classifier = 'sources' + archiveClassifier = 'sources' } task dokkaJar(type: Jar, dependsOn: dokkaHtml) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from dokkaHtml.outputDirectory } From 072258e0a7836e8b7eaa77e7c88fd68dcdb51b28 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 14 May 2023 02:16:33 +0200 Subject: [PATCH 34/62] upgrades --- .jitpack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jitpack.yml b/.jitpack.yml index f78f664..57db296 100644 --- a/.jitpack.yml +++ b/.jitpack.yml @@ -1 +1 @@ -jdk: openjdk11 \ No newline at end of file +jdk: openjdk17 \ No newline at end of file From 5e210e9023c0ccb7e20377fa5b208002703656a2 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 18 May 2023 22:10:46 +0200 Subject: [PATCH 35/62] migrate build scripts to convention plugins --- app/build.gradle | 83 --------------- app/build.gradle.kts | 59 +++++++++++ app/proguard-rules.pro | 21 ---- build-logic/convention/build.gradle.kts | 59 +++++++++++ ...droidApplicationComposeConventionPlugin.kt | 16 +++ .../AndroidApplicationConventionPlugin.kt | 34 ++++++ ...droidApplicationFlavorsConventionPlugin.kt | 13 +++ .../AndroidLibraryComposeConventionPlugin.kt | 16 +++ .../kotlin/AndroidLibraryConventionPlugin.kt | 52 +++++++++ ...ndroidLibraryPublishingConventionPlugin.kt | 42 ++++++++ .../kotlin/AndroidTestConventionPlugin.kt | 22 ++++ .../kodehighlighter/AndroidCompose.kt | 65 ++++++++++++ .../AndroidInstrumentedTests.kt | 19 ++++ .../kodehighlighter/KotlinAndroid.kt | 71 +++++++++++++ build-logic/gradle.properties | 4 + build-logic/settings.gradle.kts | 14 +++ build.gradle | 68 ------------ build.gradle.kts | 14 +++ gradle/libs.versions.toml | 51 +++++++++ library/build.gradle | 100 ------------------ library/build.gradle.kts | 44 ++++++++ library/proguard-rules.pro | 21 ---- settings.gradle | 12 --- settings.gradle.kts | 23 ++++ 24 files changed, 618 insertions(+), 305 deletions(-) delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 app/proguard-rules.pro create mode 100644 build-logic/convention/build.gradle.kts create mode 100644 build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidApplicationFlavorsConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidCompose.kt create mode 100644 build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidInstrumentedTests.kt create mode 100644 build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/KotlinAndroid.kt create mode 100644 build-logic/gradle.properties create mode 100644 build-logic/settings.gradle.kts delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 gradle/libs.versions.toml delete mode 100644 library/build.gradle create mode 100644 library/build.gradle.kts delete mode 100644 library/proguard-rules.pro delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 62d452a..0000000 --- a/app/build.gradle +++ /dev/null @@ -1,83 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-parcelize' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - - defaultConfig { - applicationId "de.markusressel.kodeeditor" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode rootProject.ext.versionCode - versionName rootProject.ext.versionName - testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' - - setProperty("archivesBaseName", "KodeEditor_v${versionName}_(${versionCode})") - - multiDexEnabled true - vectorDrawables { - useSupportLibrary true - } - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - buildFeatures { - viewBinding true - compose true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - packagingOptions { - resources { - excludes += ['/META-INF/{AL2.0,LGPL2.1}', 'LICENSE.txt', 'META-INF/DEPENDENCIES', 'META-INF/ASL2.0', 'META-INF/NOTICE', 'META-INF/LICENSE'] - pickFirsts += ['META-INF/proguard/androidx-annotations.pro'] - } - } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - composeOptions { - kotlinCompilerExtensionVersion compose_compiler_version - } - namespace 'de.markusressel.kodeeditor' -} - -dependencies { - implementation project(':library') - - // Syntax Highlighting - api("com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion") - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.9.0' - implementation "androidx.compose.ui:ui:$compose_version" - implementation "androidx.compose.material:material:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1' - implementation 'androidx.activity:activity-compose:1.7.1' - androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" - debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" - - def fuelVersion = "2.3.1" - implementation "com.github.kittinunf.fuel:fuel:$fuelVersion" - implementation "com.github.kittinunf.fuel:fuel-android:$fuelVersion" - - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' -} \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..1be7f2c --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,59 @@ +plugins { + id("kodeeditor.android.application") + id("kodeeditor.android.application.compose") + id("kodeeditor.android.application.flavors") +} + +android { + defaultConfig { + applicationId = "de.markusressel.kodeeditor" + versionCode = 1 + versionName = "4.0.1" + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + setProperty("archivesBaseName", "KodeEditor_v${versionName}_(${versionCode})") + } + + packaging { + resources { + excludes.add("/META-INF/{AL2.0,LGPL2.1}") + excludes.addAll( + listOf("LICENSE.txt", "META-INF/DEPENDENCIES", "META-INF/ASL2.0", "META-INF/NOTICE", "META-INF/LICENSE") + ) + pickFirsts.add("META-INF/proguard/androidx-annotations.pro") + } + } + + namespace = "de.markusressel.kodeeditor" +} + +dependencies { + implementation(project(":library")) + + // Syntax Highlighting + val kodeHighlighterVersion = "master-SNAPSHOT" + implementation("com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion") + + implementation(libs.kotlin.stdlib.jdk8) + + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.9.0") + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.material) + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + implementation("androidx.activity:activity-compose:1.7.1") + + val fuelVersion = "2.3.1" + implementation("com.github.kittinunf.fuel:fuel:$fuelVersion") + implementation("com.github.kittinunf.fuel:fuel-android:$fuelVersion") + + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlinx.coroutines.android) + + debugImplementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.compose.ui.tooling.preview) + + testImplementation(libs.junit4) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.androidx.test.espresso.core) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro deleted file mode 100644 index f1b4245..0000000 --- a/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts new file mode 100644 index 0000000..2b3614b --- /dev/null +++ b/build-logic/convention/build.gradle.kts @@ -0,0 +1,59 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `kotlin-dsl` +} + +group = "de.markusressel.kodeeditor.buildlogic" + +java { + // Up to Java 11 APIs are available through desugaring + // https://developer.android.com/studio/write/java11-minimal-support-table + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType().configureEach { + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } +} + +dependencies { + compileOnly(libs.android.gradle.plugin) + compileOnly(libs.kotlin.gradle.plugin) + compileOnly(libs.ksp.gradle.plugin) +} + +gradlePlugin { + plugins { + register("androidApplicationCompose") { + id = "kodeeditor.android.application.compose" + implementationClass = "AndroidApplicationComposeConventionPlugin" + } + register("androidApplication") { + id = "kodeeditor.android.application" + implementationClass = "AndroidApplicationConventionPlugin" + } + register("androidLibraryCompose") { + id = "kodeeditor.android.library.compose" + implementationClass = "AndroidLibraryComposeConventionPlugin" + } + register("androidLibrary") { + id = "kodeeditor.android.library" + implementationClass = "AndroidLibraryConventionPlugin" + } + register("androidLibraryPublishing") { + id = "kodeeditor.android.library.publishing" + implementationClass = "AndroidLibraryPublishingConventionPlugin" + } + register("androidTest") { + id = "kodeeditor.android.test" + implementationClass = "AndroidTestConventionPlugin" + } + register("androidFlavors") { + id = "kodeeditor.android.application.flavors" + implementationClass = "AndroidApplicationFlavorsConventionPlugin" + } + } +} diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt new file mode 100644 index 0000000..13856db --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt @@ -0,0 +1,16 @@ +import com.android.build.api.dsl.ApplicationExtension +import de.markusressel.kodeeditor.configureAndroidCompose +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +class AndroidApplicationComposeConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + pluginManager.apply("com.android.application") + val extension = extensions.getByType() + configureAndroidCompose(extension) + } + } + +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt new file mode 100644 index 0000000..852872d --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -0,0 +1,34 @@ +import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.variant.ApplicationAndroidComponentsExtension +import de.markusressel.kodeeditor.configureKotlinAndroid +import de.markusressel.kodeeditor.configureKotlinAndroidToolchain +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class AndroidApplicationConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.application") + apply("org.jetbrains.kotlin.android") + apply("org.jetbrains.kotlin.plugin.parcelize") + } + + group = "de.markusressel.kodeeditor.demo" + + configureKotlinAndroidToolchain() + extensions.configure { + configureKotlinAndroid(this) + defaultConfig.targetSdk = 33 + + viewBinding { + enable = true + } + } + extensions.configure { + } + } + } + +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationFlavorsConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationFlavorsConventionPlugin.kt new file mode 100644 index 0000000..74bc7c9 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationFlavorsConventionPlugin.kt @@ -0,0 +1,13 @@ +import com.android.build.api.dsl.ApplicationExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class AndroidApplicationFlavorsConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + extensions.configure { + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt new file mode 100644 index 0000000..1b242c4 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt @@ -0,0 +1,16 @@ +import com.android.build.gradle.LibraryExtension +import de.markusressel.kodeeditor.configureAndroidCompose +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +class AndroidLibraryComposeConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + pluginManager.apply("com.android.library") + val extension = extensions.getByType() + configureAndroidCompose(extension) + } + } + +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt new file mode 100644 index 0000000..750b8a3 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -0,0 +1,52 @@ +import com.android.build.api.variant.LibraryAndroidComponentsExtension +import com.android.build.gradle.LibraryExtension +import de.markusressel.kodeeditor.configureKotlinAndroid +import de.markusressel.kodeeditor.configureKotlinAndroidToolchain +import de.markusressel.kodeeditor.disableUnnecessaryAndroidTests +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.kotlin + +class AndroidLibraryConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.library") + apply("org.jetbrains.kotlin.android") + } + + group = "de.markusressel.kodeeditor.library" + + configureKotlinAndroidToolchain() + extensions.configure { + configureKotlinAndroid(this) + defaultConfig.targetSdk = 33 + } + extensions.configure { + disableUnnecessaryAndroidTests(target) + } + val libs = extensions.getByType().named("libs") + configurations.configureEach { + resolutionStrategy { + // TODO: + //cacheChangingModulesFor(0, 'seconds') + + force(libs.findLibrary("kotlin-stdlib").get()) + force(libs.findLibrary("kotlin-stdlib-jdk8").get()) + + force(libs.findLibrary("junit4").get()) + // Temporary workaround for https://issuetracker.google.com/174733673 + force("org.objenesis:objenesis:2.6") + } + } + dependencies { + add("androidTestImplementation", kotlin("test")) + add("testImplementation", kotlin("test")) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt new file mode 100644 index 0000000..8e5d712 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt @@ -0,0 +1,42 @@ +import com.android.build.gradle.LibraryExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.create + +class AndroidLibraryPublishingConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + extensions.configure { + with(pluginManager) { + apply("maven-publish") + } + publishing { + singleVariant("release") { + group = "com.github.markusressel.KodeEditor" + withJavadocJar() + withSourcesJar() + } + } + configure { + publications { + create("maven", MavenPublication::class) { + groupId = "com.github.markusressel.KodeEditor" + artifactId = target.name + version = "${target.version}" + + artifact("$buildDir/outputs/aar/${target.name}-release.aar") { + builtBy(tasks.getByName("assemble")) + } + } + } + repositories { + mavenLocal() + } + } + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt new file mode 100644 index 0000000..26a7f22 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt @@ -0,0 +1,22 @@ +import com.android.build.gradle.TestExtension +import de.markusressel.kodeeditor.configureKotlinAndroid +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class AndroidTestConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.test") + apply("org.jetbrains.kotlin.android") + } + + extensions.configure { + configureKotlinAndroid(this) + defaultConfig.targetSdk = 31 + } + } + } + +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidCompose.kt new file mode 100644 index 0000000..2dba1f2 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidCompose.kt @@ -0,0 +1,65 @@ +package de.markusressel.kodeeditor + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.io.File + +/** + * Configure Compose-specific options + */ +internal fun Project.configureAndroidCompose( + commonExtension: CommonExtension<*, *, *, *>, +) { + val libs = extensions.getByType().named("libs") + + commonExtension.apply { + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString() + } + + dependencies { + val bom = libs.findLibrary("androidx-compose-bom").get() + add("implementation", platform(bom)) + add("androidTestImplementation", platform(bom)) + } + } + + tasks.withType().configureEach { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + buildComposeMetricsParameters() + } + } +} + +private fun Project.buildComposeMetricsParameters(): List { + val metricParameters = mutableListOf() + val enableMetricsProvider = project.providers.gradleProperty("enableComposeCompilerMetrics") + val enableMetrics = (enableMetricsProvider.orNull == "true") + if (enableMetrics) { + val metricsFolder = File(project.buildDir, "compose-metrics") + metricParameters.add("-P") + metricParameters.add( + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + metricsFolder.absolutePath + ) + } + + val enableReportsProvider = project.providers.gradleProperty("enableComposeCompilerReports") + val enableReports = (enableReportsProvider.orNull == "true") + if (enableReports) { + val reportsFolder = File(project.buildDir, "compose-reports") + metricParameters.add("-P") + metricParameters.add( + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + reportsFolder.absolutePath + ) + } + return metricParameters.toList() +} diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidInstrumentedTests.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidInstrumentedTests.kt new file mode 100644 index 0000000..9bf14be --- /dev/null +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidInstrumentedTests.kt @@ -0,0 +1,19 @@ +package de.markusressel.kodeeditor + +import com.android.build.api.variant.LibraryAndroidComponentsExtension +import org.gradle.api.Project + +/** + * Disable unnecessary Android instrumented tests for the [project] if there is no `androidTest` folder. + * Otherwise, these projects would be compiled, packaged, installed and ran only to end-up with the following message: + * + * > Starting 0 tests on AVD + * + * Note: this could be improved by checking other potential sourceSets based on buildTypes and flavors. + */ +internal fun LibraryAndroidComponentsExtension.disableUnnecessaryAndroidTests( + project: Project, +) = beforeVariants { + it.enableAndroidTest = it.enableAndroidTest + && project.projectDir.resolve("src/androidTest").exists() +} diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/KotlinAndroid.kt new file mode 100644 index 0000000..22e4c18 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/KotlinAndroid.kt @@ -0,0 +1,71 @@ +package de.markusressel.kodeeditor + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.plugins.ExtensionAware +import org.gradle.kotlin.dsl.* +import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +/** + * Configure base Kotlin with Android options + */ +internal fun Project.configureKotlinAndroid( + commonExtension: CommonExtension<*, *, *, *>, +) { + commonExtension.apply { + compileSdk = 33 + + defaultConfig { + minSdk = 21 + } + + compileOptions { + // Up to Java 11 APIs are available through desugaring + // https://developer.android.com/studio/write/java11-minimal-support-table + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + isCoreLibraryDesugaringEnabled = true + } + } + + // Use withType to workaround https://youtrack.jetbrains.com/issue/KT-55947 + tasks.withType().configureEach { + kotlinOptions { + // Set JVM target to 11 + jvmTarget = JavaVersion.VERSION_17.toString() + // Treat all Kotlin warnings as errors (disabled by default) + // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties + val warningsAsErrors: String? by project + allWarningsAsErrors = warningsAsErrors.toBoolean() + freeCompilerArgs = freeCompilerArgs + listOf( + "-opt-in=kotlin.RequiresOptIn", + // Enable experimental coroutines APIs, including Flow + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-opt-in=kotlinx.coroutines.FlowPreview", + ) + } + } + + val libs = extensions.getByType().named("libs") + + dependencies { + add("coreLibraryDesugaring", libs.findLibrary("android.desugarJdkLibs").get()) + } +} + +fun CommonExtension<*, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { + (this as ExtensionAware).extensions.configure("kotlinOptions", block) +} + +/** + * Configure Kotlin's jvm toolchain for Android projects + */ +internal fun Project.configureKotlinAndroidToolchain() { + extensions.configure { + jvmToolchain(17) + } +} diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties new file mode 100644 index 0000000..1c9073e --- /dev/null +++ b/build-logic/gradle.properties @@ -0,0 +1,4 @@ +# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534 +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configureondemand=true diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..2907fbf --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,14 @@ +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" +include(":convention") diff --git a/build.gradle b/build.gradle deleted file mode 100644 index c7cf2f1..0000000 --- a/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext.kotlin_version = '1.8.21' - ext.dokka_version = '1.6.21' - - ext { - group = 'com.github.markusressel' - - gradle_plugin_version = '8.0.0' - - minSdkVersion = 21 - versionName = "4.0.1" - versionCode = 1 - - compileSdkVersion = 33 - targetSdkVersion = 33 - buildToolsVersion = "30.0.3" - - // DEPENDENCIES - -// kodeHighlighterVersion = "v3.0.0" - kodeHighlighterVersion = "master-SNAPSHOT" - - javaxAnnotationVersion = "10.0-b28" - aboutlibrariesVersion = "8.2.0" - - flowBindingVersion = "1.0.0" - - timberKtVersion = "1.5.1" - compose_compiler_version = '1.4.7' - compose_version = '1.4.0-alpha03' - } - - repositories { - google() - jcenter() - } - - dependencies { - classpath "com.android.tools.build:gradle:$gradle_plugin_version" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' - classpath("org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}") - } -} - -allprojects { - configurations.all() { - resolutionStrategy.cacheChangingModulesFor 0, 'seconds' - - resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - } -} - -apply plugin: 'kotlin' - -compileKotlin { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8.toString() - } -} -compileTestKotlin { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8.toString() - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..746bfb0 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,14 @@ +buildscript { + repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") + } +} + +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.kotlin.serialization) apply false + alias(libs.plugins.ksp) apply false +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..8664e60 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,51 @@ +[versions] +androidDesugarJdkLibs = "1.2.2" +androidGradlePlugin = "8.0.0" +androidxComposeBom = "2023.01.00" +androidxComposeCompiler = "1.4.7" +androidxComposeUi = "1.4.3" +androidxComposeUiText = "1.4.3" +androidxTestExtJunit = "1.1.5" +androidxTestEspressoCore = "3.5.1" +dokkaGradlePlugin = "1.7.20" +junit4 = "4.13.2" +kotlin = "1.8.21" +kotlinCoroutinesCore = "1.6.4" +kotlinCoroutinesAndroid = "1.6.4" +ksp = "1.8.20-1.0.11" + + +[libraries] +android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" } +android-gradle-plugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } + +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } +androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "androidxComposeUi" } +androidx-compose-ui-text = { group = "androidx.compose.ui", name = "ui-text", version.ref = "androidxComposeUiText" } +androidx-compose-material = { group = "androidx.compose.material", name = "material", version.ref = "androidxComposeUiText" } +androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } + +dokka-gradle-plugin = { group = "org.jetbrains.dokka", name = "dokka-gradle-plugin", version.ref = "dokkaGradlePlugin" } + +kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } +kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } +kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" } +kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinCoroutinesCore" } +kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinCoroutinesAndroid" } + +ksp-gradle-plugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } + + + +junit4 = { group = "junit", name = "junit", version.ref = "junit4" } +androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxTestExtJunit" } +androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxTestEspressoCore" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } +android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } diff --git a/library/build.gradle b/library/build.gradle deleted file mode 100644 index ac7d614..0000000 --- a/library/build.gradle +++ /dev/null @@ -1,100 +0,0 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'org.jetbrains.dokka' - -group = rootProject.ext.group - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - - defaultConfig { - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - buildFeatures { - compose true - } - - composeOptions { - kotlinCompilerExtensionVersion compose_compiler_version - } - namespace 'de.markusressel.kodeeditor.library' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" -// api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' - - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.annotation:annotation:1.6.0' - - implementation "androidx.compose.ui:ui:1.4.3" - implementation "androidx.compose.material:material:1.4.3" - implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" - - debugImplementation "androidx.compose.ui:ui-tooling:1.4.3" - implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" - - // RxFlow - implementation "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBindingVersion" - - // Lifecycle - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1" - - // Syntax Highlighting - api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") { - changing = true - } - - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" - - // Zoom Layout Container - api 'com.otaliastudios:zoomlayout:1.9.0' - - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' -} - -configurations.all { - resolutionStrategy.cacheChangingModulesFor 0, 'seconds' -} - -// build a jar with source files -task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - archiveClassifier = 'sources' -} - -task dokkaJar(type: Jar, dependsOn: dokkaHtml) { - archiveClassifier = 'javadoc' - from dokkaHtml.outputDirectory -} - -dokkaHtml.configure { - dokkaSourceSets { - named("main") { - noAndroidSdkLink.set(false) - } - } -} - -artifacts { - archives sourcesJar - archives dokkaJar -} diff --git a/library/build.gradle.kts b/library/build.gradle.kts new file mode 100644 index 0000000..aa15f38 --- /dev/null +++ b/library/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("kodeeditor.android.library") + id("kodeeditor.android.library.compose") +} + +group = "de.markusressel.kodeeditor" + +android { + namespace = "de.markusressel.kodeeditor.library" +} + +dependencies { + implementation(libs.kotlin.stdlib.jdk8) +// api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' + + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("androidx.annotation:annotation:1.6.0") + + implementation("androidx.compose.ui:ui:1.4.3") + implementation("androidx.compose.material:material:1.4.3") + + debugImplementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.compose.ui.tooling.preview) + + // RxFlow + implementation("io.github.reactivecircus.flowbinding:flowbinding-android:+") + + // Lifecycle + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + + // Syntax Highlighting + val kodeHighlighterVersion = "master-SNAPSHOT" + api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") + + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlinx.coroutines.android) + + // Zoom Layout Container + api("com.otaliastudios:zoomlayout:1.9.0") + + testImplementation(libs.junit4) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.androidx.test.espresso.core) +} diff --git a/library/proguard-rules.pro b/library/proguard-rules.pro deleted file mode 100644 index f1b4245..0000000 --- a/library/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 5243a55..0000000 --- a/settings.gradle +++ /dev/null @@ -1,12 +0,0 @@ -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - maven { url "https://jitpack.io" } - } -} - -rootProject.name = "KodeEditor" - -include ':app', ':library' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..9938e0a --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,23 @@ +pluginManagement { + includeBuild("build-logic") + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") + } +} + +rootProject.name = "KodeEditor" +if (System.getenv("JITPACK").toBoolean().not()) + include(":app") +include(":library") From 946b83a071f18f4d5c1e077f3782d27f4416f3e7 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 18 May 2023 22:21:18 +0200 Subject: [PATCH 36/62] change namespace of demo app, remove group definition of library --- app/build.gradle.kts | 2 +- library/build.gradle.kts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1be7f2c..d051db9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -24,7 +24,7 @@ android { } } - namespace = "de.markusressel.kodeeditor" + namespace = "de.markusressel.kodeeditor.demo" } dependencies { diff --git a/library/build.gradle.kts b/library/build.gradle.kts index aa15f38..cc57a12 100644 --- a/library/build.gradle.kts +++ b/library/build.gradle.kts @@ -3,8 +3,6 @@ plugins { id("kodeeditor.android.library.compose") } -group = "de.markusressel.kodeeditor" - android { namespace = "de.markusressel.kodeeditor.library" } From 6d80de9ae5a6bfab6e604b021acbc25cda989d11 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 18 May 2023 22:36:21 +0200 Subject: [PATCH 37/62] update targetSdk --- .../convention/src/main/kotlin/AndroidTestConventionPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt index 26a7f22..f86c20e 100644 --- a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt @@ -14,7 +14,7 @@ class AndroidTestConventionPlugin : Plugin { extensions.configure { configureKotlinAndroid(this) - defaultConfig.targetSdk = 31 + defaultConfig.targetSdk = 33 } } } From 92173aa2ce68c1d87cf390e0037d369b3e4f7110 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 18 May 2023 22:37:06 +0200 Subject: [PATCH 38/62] fix package --- .../{kodehighlighter => kodeeditor}/AndroidCompose.kt | 0 .../{kodehighlighter => kodeeditor}/AndroidInstrumentedTests.kt | 0 .../markusressel/{kodehighlighter => kodeeditor}/KotlinAndroid.kt | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename build-logic/convention/src/main/kotlin/de/markusressel/{kodehighlighter => kodeeditor}/AndroidCompose.kt (100%) rename build-logic/convention/src/main/kotlin/de/markusressel/{kodehighlighter => kodeeditor}/AndroidInstrumentedTests.kt (100%) rename build-logic/convention/src/main/kotlin/de/markusressel/{kodehighlighter => kodeeditor}/KotlinAndroid.kt (100%) diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt similarity index 100% rename from build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidCompose.kt rename to build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidInstrumentedTests.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidInstrumentedTests.kt similarity index 100% rename from build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/AndroidInstrumentedTests.kt rename to build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidInstrumentedTests.kt diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt similarity index 100% rename from build-logic/convention/src/main/kotlin/de/markusressel/kodehighlighter/KotlinAndroid.kt rename to build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt From f12768cb871d346151b4a97b42f9d1376cf49dad Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 18 May 2023 22:39:58 +0200 Subject: [PATCH 39/62] add missing publishing plugin --- library/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/library/build.gradle.kts b/library/build.gradle.kts index cc57a12..b795122 100644 --- a/library/build.gradle.kts +++ b/library/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("kodeeditor.android.library") id("kodeeditor.android.library.compose") + id("kodeeditor.android.library.publishing") } android { From b4de0ec01c518f9e0d460e1fccd6f0531c0156d4 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Thu, 18 May 2023 22:41:59 +0200 Subject: [PATCH 40/62] remove dokkaJar task --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 921fb87..e122fb9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: with: java-version: 17 - name: Perform base checks - run: ./gradlew app:assembleDebug library:sourcesJar library:dokkaJar --stacktrace + run: ./gradlew app:assembleDebug library:sourcesJar --stacktrace ANDROID_UNIT_TESTS: name: Unit Tests runs-on: ubuntu-latest From abeb87da03a4cfa197a73fb444471f01899a5ad5 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 19 May 2023 23:41:20 +0200 Subject: [PATCH 41/62] remove unused config --- .github/config.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .github/config.yml diff --git a/.github/config.yml b/.github/config.yml deleted file mode 100644 index 3ea88e9..0000000 --- a/.github/config.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome - -# Comment to be posted to on first time issues -newIssueWelcomeComment: > - Thanks for opening your first issue here! :tada: - -# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome - -# Comment to be posted to on PRs from first time contributors in your repository -newPRWelcomeComment: > - Thanks for opening this pull request! :nerd_face: - -# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge - -# Comment to be posted to on pull requests merged by a first time user -firstPRMergeComment: > - Congrats on merging your first pull request here! You should be proud of yourself :1st_place_medal: - ![Congratulations](https://media.giphy.com/media/ehhuGD0nByYxO/giphy.gif) - -# It is recommend to include as many gifs and emojis as possible From 87dda9019778c2188a953a89bee303b3723372e9 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 00:24:39 +0200 Subject: [PATCH 42/62] version migrations --- gradle/libs.versions.toml | 17 ++++++++++++++++- library/build.gradle.kts | 17 ++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8664e60..13d92cf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,24 +1,34 @@ [versions] androidDesugarJdkLibs = "1.2.2" androidGradlePlugin = "8.0.0" +androidxAnnotation = "1.6.0" +androidxAppCompat = "1.6.1" androidxComposeBom = "2023.01.00" androidxComposeCompiler = "1.4.7" androidxComposeUi = "1.4.3" androidxComposeUiText = "1.4.3" +androidxLifecycle = "2.6.1" androidxTestExtJunit = "1.1.5" androidxTestEspressoCore = "3.5.1" dokkaGradlePlugin = "1.7.20" +flowbindingAndroid = "1.2.0" junit4 = "4.13.2" kotlin = "1.8.21" kotlinCoroutinesCore = "1.6.4" kotlinCoroutinesAndroid = "1.6.4" +kodehighlighter = "v4.0.0" ksp = "1.8.20-1.0.11" +zoomlayout = "1.9.0" [libraries] android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" } android-gradle-plugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } +androidx-annotation = { group = "androidx.annotation", name = "annotation", version.ref = "androidxAnnotation" } + +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" } + androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "androidxComposeUi" } androidx-compose-ui-text = { group = "androidx.compose.ui", name = "ui-text", version.ref = "androidxComposeUiText" } @@ -26,8 +36,12 @@ androidx-compose-material = { group = "androidx.compose.material", name = "mater androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "androidxLifecycle" } + dokka-gradle-plugin = { group = "org.jetbrains.dokka", name = "dokka-gradle-plugin", version.ref = "dokkaGradlePlugin" } +flowbinding-android = { group = "io.github.reactivecircus.flowbinding", name = "flowbinding-android", version.ref = "flowbindingAndroid" } + kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" } @@ -36,7 +50,8 @@ kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx- ksp-gradle-plugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } - +kodehighlighter-core = { group = "com.github.markusressel.KodeHighlighter", name = "core", version.ref = "kodehighlighter" } +zoomlayout = { group = "com.otaliastudios", name = "zoomlayout", version.ref = "zoomlayout" } junit4 = { group = "junit", name = "junit", version.ref = "junit4" } androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxTestExtJunit" } diff --git a/library/build.gradle.kts b/library/build.gradle.kts index b795122..57faea3 100644 --- a/library/build.gradle.kts +++ b/library/build.gradle.kts @@ -12,30 +12,29 @@ dependencies { implementation(libs.kotlin.stdlib.jdk8) // api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("androidx.annotation:annotation:1.6.0") + implementation(libs.androidx.appcompat) + implementation(libs.androidx.annotation) - implementation("androidx.compose.ui:ui:1.4.3") - implementation("androidx.compose.material:material:1.4.3") + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.material) debugImplementation(libs.androidx.compose.ui.tooling) implementation(libs.androidx.compose.ui.tooling.preview) // RxFlow - implementation("io.github.reactivecircus.flowbinding:flowbinding-android:+") + implementation(libs.flowbinding.android) // Lifecycle - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + implementation(libs.androidx.lifecycle.runtime.ktx) // Syntax Highlighting - val kodeHighlighterVersion = "master-SNAPSHOT" - api("com.github.markusressel.KodeHighlighter:core:$kodeHighlighterVersion") + api(libs.kodehighlighter.core) implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.android) // Zoom Layout Container - api("com.otaliastudios:zoomlayout:1.9.0") + api(libs.zoomlayout) testImplementation(libs.junit4) androidTestImplementation(libs.androidx.test.ext.junit) From 1fbb22c860b652e81484f67afcff19832926751a Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 00:30:56 +0200 Subject: [PATCH 43/62] fix imports --- app/build.gradle.kts | 3 +-- .../java/de/markusressel/kodeeditor/ComposeMainActivity.kt | 1 + app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt | 3 ++- .../src/main/kotlin/AndroidApplicationConventionPlugin.kt | 3 +++ gradle/libs.versions.toml | 4 +++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d051db9..7f8febd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -31,8 +31,7 @@ dependencies { implementation(project(":library")) // Syntax Highlighting - val kodeHighlighterVersion = "master-SNAPSHOT" - implementation("com.github.markusressel.KodeHighlighter:markdown:$kodeHighlighterVersion") + implementation(libs.kodehighlighter.markdown) implementation(libs.kotlin.stdlib.jdk8) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt index 2bb2d75..cba2e11 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import de.markusressel.kodeeditor.demo.R import de.markusressel.kodeeditor.library.compose.KodeEditor import de.markusressel.kodeeditor.library.compose.KodeEditorDefaults import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme diff --git a/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt index 0a8bc01..d10ab18 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt @@ -6,7 +6,8 @@ import android.view.Gravity import androidx.annotation.RawRes import androidx.appcompat.app.AppCompatActivity import com.github.kittinunf.fuel.Fuel -import de.markusressel.kodeeditor.databinding.ActivityMainBinding +import de.markusressel.kodeeditor.demo.R +import de.markusressel.kodeeditor.demo.databinding.ActivityMainBinding import de.markusressel.kodeeditor.library.extensions.dpToPx import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorScheme diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 852872d..6e7352d 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -22,6 +22,9 @@ class AndroidApplicationConventionPlugin : Plugin { configureKotlinAndroid(this) defaultConfig.targetSdk = 33 + dataBinding { + enable = true + } viewBinding { enable = true } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 13d92cf..6c9b330 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ junit4 = "4.13.2" kotlin = "1.8.21" kotlinCoroutinesCore = "1.6.4" kotlinCoroutinesAndroid = "1.6.4" -kodehighlighter = "v4.0.0" +kodehighlighter = "4.0.0" ksp = "1.8.20-1.0.11" zoomlayout = "1.9.0" @@ -51,6 +51,8 @@ kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx- ksp-gradle-plugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } kodehighlighter-core = { group = "com.github.markusressel.KodeHighlighter", name = "core", version.ref = "kodehighlighter" } +kodehighlighter-markdown = { group = "com.github.markusressel.KodeHighlighter", name = "markdown", version.ref = "kodehighlighter" } + zoomlayout = { group = "com.otaliastudios", name = "zoomlayout", version.ref = "zoomlayout" } junit4 = { group = "junit", name = "junit", version.ref = "junit4" } From 92f21498803acaf3bcdfd363ed8d6c3b0b0697ba Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 00:39:50 +0200 Subject: [PATCH 44/62] remove sourcesJar task --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b730d2..5e4a7c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: distribution: temurin cache: 'gradle' - name: Perform base checks - run: ./gradlew app:assembleDebug library:sourcesJar --stacktrace + run: ./gradlew app:assembleDebug --stacktrace ANDROID_UNIT_TESTS: name: Unit Tests runs-on: ubuntu-latest From 58fba3460ba73e8e72e08989a374b5f0c0e3e167 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 01:07:12 +0200 Subject: [PATCH 45/62] update README.md --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index bc12c36..07213e0 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,10 @@ -# KodeEditor +# KodeEditor [![codebeat badge](https://codebeat.co/badges/f7fa8602-1d15-457e-904d-cb585e984952)](https://codebeat.co/projects/github-com-markusressel-kodeeditor-master) A simple code editor with syntax highlighting and pinch to zoom ![Editing](https://thumbs.gfycat.com/TalkativeGrandIchthyosaurs-size_restricted.gif) ![Scroll and zoom](https://thumbs.gfycat.com/BouncyLividBlackbear-size_restricted.gif) ![Minimap](https://thumbs.gfycat.com/VigorousDimFrog-size_restricted.gif) -# Build Status - -| Master | -|--------| -| [![codebeat badge](https://codebeat.co/badges/f7fa8602-1d15-457e-904d-cb585e984952)](https://codebeat.co/projects/github-com-markusressel-kodeeditor-master) | - # Features * [x] Pinch-To-Zoom * [x] Line numbers From da575a16c3063b9fa28842a2acc0011db0512c0d Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 01:24:51 +0200 Subject: [PATCH 46/62] added fetch-depth to checkout to fix telegram notification script --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e4a7c1..8406cd7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,6 +34,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + # required for telegram notifications on PRs + fetch-depth: 0 - uses: actions/setup-java@v3 with: java-version: 17 From c9aa4b74b79e8084d9957dfe06014cdb8deb9365 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 01:30:44 +0200 Subject: [PATCH 47/62] try to fix PR notifications --- .ci/notify.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/notify.sh b/.ci/notify.sh index a9edf69..0b8353e 100755 --- a/.ci/notify.sh +++ b/.ci/notify.sh @@ -19,7 +19,7 @@ fi if [[ -n "${GITHUB_HEAD_REF}" ]]; then # this is a PR - COMMITS_INVOLVED=$(git log --oneline ^"${GITHUB_BASE_REF}" HEAD) + COMMITS_INVOLVED=$(git log --oneline ^"origin/${GITHUB_BASE_REF}" HEAD) PR_LINK_TEXT=$(cat < Date: Sat, 20 May 2023 01:56:31 +0200 Subject: [PATCH 48/62] fix demo app package --- .../kodeeditor/{ => demo}/ComposeMainActivity.kt | 5 ++--- .../de/markusressel/kodeeditor/{ => demo}/MainActivity.kt | 3 +-- .../de/markusressel/kodeeditor/{ => demo}/ui/theme/Color.kt | 2 +- .../de/markusressel/kodeeditor/{ => demo}/ui/theme/Shape.kt | 2 +- .../de/markusressel/kodeeditor/{ => demo}/ui/theme/Theme.kt | 2 +- .../de/markusressel/kodeeditor/{ => demo}/ui/theme/Type.kt | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) rename app/src/main/java/de/markusressel/kodeeditor/{ => demo}/ComposeMainActivity.kt (97%) rename app/src/main/java/de/markusressel/kodeeditor/{ => demo}/MainActivity.kt (96%) rename app/src/main/java/de/markusressel/kodeeditor/{ => demo}/ui/theme/Color.kt (78%) rename app/src/main/java/de/markusressel/kodeeditor/{ => demo}/ui/theme/Shape.kt (85%) rename app/src/main/java/de/markusressel/kodeeditor/{ => demo}/ui/theme/Theme.kt (95%) rename app/src/main/java/de/markusressel/kodeeditor/{ => demo}/ui/theme/Type.kt (94%) diff --git a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/demo/ComposeMainActivity.kt similarity index 97% rename from app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt rename to app/src/main/java/de/markusressel/kodeeditor/demo/ComposeMainActivity.kt index cba2e11..b9c3108 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ComposeMainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/demo/ComposeMainActivity.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor +package de.markusressel.kodeeditor.demo import android.os.Bundle import androidx.activity.ComponentActivity @@ -20,10 +20,9 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import de.markusressel.kodeeditor.demo.R +import de.markusressel.kodeeditor.demo.ui.theme.KodeEditorTheme import de.markusressel.kodeeditor.library.compose.KodeEditor import de.markusressel.kodeeditor.library.compose.KodeEditorDefaults -import de.markusressel.kodeeditor.ui.theme.KodeEditorTheme import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook import de.markusressel.kodehighlighter.language.markdown.colorscheme.DarkBackgroundColorSchemeWithSpanStyle diff --git a/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt b/app/src/main/java/de/markusressel/kodeeditor/demo/MainActivity.kt similarity index 96% rename from app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt rename to app/src/main/java/de/markusressel/kodeeditor/demo/MainActivity.kt index d10ab18..8321229 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/MainActivity.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/demo/MainActivity.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor +package de.markusressel.kodeeditor.demo import android.graphics.Color import android.os.Bundle @@ -6,7 +6,6 @@ import android.view.Gravity import androidx.annotation.RawRes import androidx.appcompat.app.AppCompatActivity import com.github.kittinunf.fuel.Fuel -import de.markusressel.kodeeditor.demo.R import de.markusressel.kodeeditor.demo.databinding.ActivityMainBinding import de.markusressel.kodeeditor.library.extensions.dpToPx import de.markusressel.kodehighlighter.language.markdown.MarkdownRuleBook diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Color.kt similarity index 78% rename from app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt rename to app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Color.kt index 09ce275..fb44652 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Color.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Color.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor.ui.theme +package de.markusressel.kodeeditor.demo.ui.theme import androidx.compose.ui.graphics.Color diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Shape.kt similarity index 85% rename from app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt rename to app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Shape.kt index 90951f8..90768f9 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Shape.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Shape.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor.ui.theme +package de.markusressel.kodeeditor.demo.ui.theme import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Shapes diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Theme.kt similarity index 95% rename from app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt rename to app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Theme.kt index 70e5bad..5d1c9ce 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Theme.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Theme.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor.ui.theme +package de.markusressel.kodeeditor.demo.ui.theme import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material.MaterialTheme diff --git a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Type.kt similarity index 94% rename from app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt rename to app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Type.kt index 0384128..8a9dddd 100644 --- a/app/src/main/java/de/markusressel/kodeeditor/ui/theme/Type.kt +++ b/app/src/main/java/de/markusressel/kodeeditor/demo/ui/theme/Type.kt @@ -1,4 +1,4 @@ -package de.markusressel.kodeeditor.ui.theme +package de.markusressel.kodeeditor.demo.ui.theme import androidx.compose.material.Typography import androidx.compose.ui.text.TextStyle From 3ddcafda2c8fa0e3ab980a03b389857ac5ba244e Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 20 May 2023 01:57:49 +0200 Subject: [PATCH 49/62] lint fix --- app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b4a90b2..12106e0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,7 @@ + android:exported="false" /> \ No newline at end of file From 7c23a3f07337356ffb00e22e45c9e3f41e77efae Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 16 Dec 2023 22:30:03 +0100 Subject: [PATCH 50/62] update dependencies --- app/build.gradle.kts | 19 ++++----------- build-logic/convention/build.gradle.kts | 1 + .../AndroidApplicationConventionPlugin.kt | 17 ++++++++++++- .../kotlin/AndroidLibraryConventionPlugin.kt | 3 ++- ...ndroidLibraryPublishingConventionPlugin.kt | 2 +- .../kotlin/AndroidTestConventionPlugin.kt | 3 ++- .../markusressel/kodeeditor/AndroidCompose.kt | 6 ++--- .../markusressel/kodeeditor/KotlinAndroid.kt | 9 ++++--- gradle.properties | 1 - gradle/libs.versions.toml | 24 +++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- 11 files changed, 48 insertions(+), 39 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7f8febd..35941b3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,26 +5,15 @@ plugins { } android { + namespace = "de.markusressel.kodeeditor.demo" + defaultConfig { applicationId = "de.markusressel.kodeeditor" versionCode = 1 versionName = "4.0.1" - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" setProperty("archivesBaseName", "KodeEditor_v${versionName}_(${versionCode})") } - - packaging { - resources { - excludes.add("/META-INF/{AL2.0,LGPL2.1}") - excludes.addAll( - listOf("LICENSE.txt", "META-INF/DEPENDENCIES", "META-INF/ASL2.0", "META-INF/NOTICE", "META-INF/LICENSE") - ) - pickFirsts.add("META-INF/proguard/androidx-annotations.pro") - } - } - - namespace = "de.markusressel.kodeeditor.demo" } dependencies { @@ -35,11 +24,11 @@ dependencies { implementation(libs.kotlin.stdlib.jdk8) - implementation("androidx.appcompat:appcompat:1.6.1") + implementation(libs.androidx.appcompat) implementation("com.google.android.material:material:1.9.0") implementation(libs.androidx.compose.ui) implementation(libs.androidx.compose.material) - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + implementation(libs.androidx.lifecycle.runtime.ktx) implementation("androidx.activity:activity-compose:1.7.1") val fuelVersion = "2.3.1" diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 2b3614b..36efc20 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -5,6 +5,7 @@ plugins { } group = "de.markusressel.kodeeditor.buildlogic" +version = "0.1.0" java { // Up to Java 11 APIs are available through desugaring diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 6e7352d..c8e5c75 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -1,5 +1,6 @@ import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension +import de.markusressel.kodeeditor.TARGET_SDK import de.markusressel.kodeeditor.configureKotlinAndroid import de.markusressel.kodeeditor.configureKotlinAndroidToolchain import org.gradle.api.Plugin @@ -20,7 +21,11 @@ class AndroidApplicationConventionPlugin : Plugin { configureKotlinAndroidToolchain() extensions.configure { configureKotlinAndroid(this) - defaultConfig.targetSdk = 33 + + defaultConfig { + targetSdk = TARGET_SDK + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } dataBinding { enable = true @@ -28,6 +33,16 @@ class AndroidApplicationConventionPlugin : Plugin { viewBinding { enable = true } + + packaging { + resources { + excludes.add("/META-INF/{AL2.0,LGPL2.1}") + excludes.addAll( + listOf("LICENSE.txt", "META-INF/DEPENDENCIES", "META-INF/ASL2.0", "META-INF/NOTICE", "META-INF/LICENSE") + ) + pickFirsts.add("META-INF/proguard/androidx-annotations.pro") + } + } } extensions.configure { } diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index 750b8a3..840d065 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -1,5 +1,6 @@ import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.gradle.LibraryExtension +import de.markusressel.kodeeditor.TARGET_SDK import de.markusressel.kodeeditor.configureKotlinAndroid import de.markusressel.kodeeditor.configureKotlinAndroidToolchain import de.markusressel.kodeeditor.disableUnnecessaryAndroidTests @@ -24,7 +25,7 @@ class AndroidLibraryConventionPlugin : Plugin { configureKotlinAndroidToolchain() extensions.configure { configureKotlinAndroid(this) - defaultConfig.targetSdk = 33 + defaultConfig.targetSdk = TARGET_SDK } extensions.configure { disableUnnecessaryAndroidTests(target) diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt index 8e5d712..8a50968 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt @@ -27,7 +27,7 @@ class AndroidLibraryPublishingConventionPlugin : Plugin { artifactId = target.name version = "${target.version}" - artifact("$buildDir/outputs/aar/${target.name}-release.aar") { + artifact("${layout.buildDirectory.get().asFile}/outputs/aar/${target.name}-release.aar") { builtBy(tasks.getByName("assemble")) } } diff --git a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt index f86c20e..ede625f 100644 --- a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt @@ -1,4 +1,5 @@ import com.android.build.gradle.TestExtension +import de.markusressel.kodeeditor.TARGET_SDK import de.markusressel.kodeeditor.configureKotlinAndroid import org.gradle.api.Plugin import org.gradle.api.Project @@ -14,7 +15,7 @@ class AndroidTestConventionPlugin : Plugin { extensions.configure { configureKotlinAndroid(this) - defaultConfig.targetSdk = 33 + defaultConfig.targetSdk = TARGET_SDK } } } diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt index 2dba1f2..6e4fead 100644 --- a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt @@ -13,7 +13,7 @@ import java.io.File * Configure Compose-specific options */ internal fun Project.configureAndroidCompose( - commonExtension: CommonExtension<*, *, *, *>, + commonExtension: CommonExtension<*, *, *, *, *>, ) { val libs = extensions.getByType().named("libs") @@ -45,7 +45,7 @@ private fun Project.buildComposeMetricsParameters(): List { val enableMetricsProvider = project.providers.gradleProperty("enableComposeCompilerMetrics") val enableMetrics = (enableMetricsProvider.orNull == "true") if (enableMetrics) { - val metricsFolder = File(project.buildDir, "compose-metrics") + val metricsFolder = File(project.layout.buildDirectory.get().asFile, "compose-metrics") metricParameters.add("-P") metricParameters.add( "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + metricsFolder.absolutePath @@ -55,7 +55,7 @@ private fun Project.buildComposeMetricsParameters(): List { val enableReportsProvider = project.providers.gradleProperty("enableComposeCompilerReports") val enableReports = (enableReportsProvider.orNull == "true") if (enableReports) { - val reportsFolder = File(project.buildDir, "compose-reports") + val reportsFolder = File(project.layout.buildDirectory.get().asFile, "compose-reports") metricParameters.add("-P") metricParameters.add( "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + reportsFolder.absolutePath diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt index 22e4c18..de9c68c 100644 --- a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt @@ -10,14 +10,17 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +const val COMPILE_SDK = 34 +const val TARGET_SDK = 34 + /** * Configure base Kotlin with Android options */ internal fun Project.configureKotlinAndroid( - commonExtension: CommonExtension<*, *, *, *>, + commonExtension: CommonExtension<*, *, *, *, *>, ) { commonExtension.apply { - compileSdk = 33 + compileSdk = COMPILE_SDK defaultConfig { minSdk = 21 @@ -57,7 +60,7 @@ internal fun Project.configureKotlinAndroid( } } -fun CommonExtension<*, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { +fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { (this as ExtensionAware).extensions.configure("kotlinOptions", block) } diff --git a/gradle.properties b/gradle.properties index 671783c..336247a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,6 +13,5 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true android.useAndroidX=true android.enableJetifier=true -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6c9b330..b80dc1b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,23 +1,23 @@ [versions] -androidDesugarJdkLibs = "1.2.2" -androidGradlePlugin = "8.0.0" -androidxAnnotation = "1.6.0" +androidDesugarJdkLibs = "2.0.4" +androidGradlePlugin = "8.2.0" +androidxAnnotation = "1.7.1" androidxAppCompat = "1.6.1" -androidxComposeBom = "2023.01.00" -androidxComposeCompiler = "1.4.7" -androidxComposeUi = "1.4.3" -androidxComposeUiText = "1.4.3" -androidxLifecycle = "2.6.1" +androidxComposeBom = "2023.10.01" +androidxComposeCompiler = "1.5.5" +androidxComposeUi = "1.5.4" +androidxComposeUiText = "1.5.4" +androidxLifecycle = "2.6.2" androidxTestExtJunit = "1.1.5" androidxTestEspressoCore = "3.5.1" dokkaGradlePlugin = "1.7.20" flowbindingAndroid = "1.2.0" junit4 = "4.13.2" -kotlin = "1.8.21" -kotlinCoroutinesCore = "1.6.4" -kotlinCoroutinesAndroid = "1.6.4" +kotlin = "1.9.20" +kotlinCoroutinesCore = "1.7.3" +kotlinCoroutinesAndroid = "1.7.3" kodehighlighter = "4.0.0" -ksp = "1.8.20-1.0.11" +ksp = "1.9.0-1.0.13" zoomlayout = "1.9.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index de840f0..a6a74fa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip From 5284510a9fd389f062bee2c8b75d0393e68e5780 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 17 Dec 2023 00:41:17 +0100 Subject: [PATCH 51/62] update ksp --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b80dc1b..d5a6323 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ kotlin = "1.9.20" kotlinCoroutinesCore = "1.7.3" kotlinCoroutinesAndroid = "1.7.3" kodehighlighter = "4.0.0" -ksp = "1.9.0-1.0.13" +ksp = "1.9.20-1.0.14" zoomlayout = "1.9.0" From b205738f2edd241a7ee6db9bec5bbaae8c8fb08f Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 18 Dec 2023 19:49:45 +0100 Subject: [PATCH 52/62] use gradle 8.2 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a6a74fa..ebe1571 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip From 505fa5986470c1e3d108c3feb62568ffc89c484d Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 18 Dec 2023 20:05:27 +0100 Subject: [PATCH 53/62] fix published groupId and artifactId --- .../main/kotlin/AndroidLibraryPublishingConventionPlugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt index 8a50968..7ca1926 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryPublishingConventionPlugin.kt @@ -23,8 +23,8 @@ class AndroidLibraryPublishingConventionPlugin : Plugin { configure { publications { create("maven", MavenPublication::class) { - groupId = "com.github.markusressel.KodeEditor" - artifactId = target.name + groupId = "com.github.markusressel" + artifactId = "KodeEditor" version = "${target.version}" artifact("${layout.buildDirectory.get().asFile}/outputs/aar/${target.name}-release.aar") { From d3502b0bf108e181a7f8b99e76d7d887d7904dc3 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 1 Jan 2024 22:16:44 +0100 Subject: [PATCH 54/62] fix line numbers not updating --- .../de/markusressel/kodeeditor/library/compose/LineNumbers.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt index 8835e72..7fcc2e4 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt @@ -36,7 +36,7 @@ fun LineNumbers( backgroundColor: Color, textColor: Color = Color.Unspecified, ) { - val lineNumbers by remember { + val lineNumbers by remember(text) { val lineCount = text.lines().size val lineText = (1..lineCount).joinToString(separator = "\n") mutableStateOf(lineText) From 735acab88aa446ceeea46970fe16efc06439e5f6 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 15 Mar 2024 23:36:03 +0100 Subject: [PATCH 55/62] update dependencies --- .../de/markusressel/kodeeditor/AndroidCompose.kt | 2 +- .../de/markusressel/kodeeditor/KotlinAndroid.kt | 4 ++-- gradle/libs.versions.toml | 16 ++++++++-------- gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt index 6e4fead..5db304f 100644 --- a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt @@ -13,7 +13,7 @@ import java.io.File * Configure Compose-specific options */ internal fun Project.configureAndroidCompose( - commonExtension: CommonExtension<*, *, *, *, *>, + commonExtension: CommonExtension<*, *, *, *, *, *>, ) { val libs = extensions.getByType().named("libs") diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt index de9c68c..ba21968 100644 --- a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/KotlinAndroid.kt @@ -17,7 +17,7 @@ const val TARGET_SDK = 34 * Configure base Kotlin with Android options */ internal fun Project.configureKotlinAndroid( - commonExtension: CommonExtension<*, *, *, *, *>, + commonExtension: CommonExtension<*, *, *, *, *, *>, ) { commonExtension.apply { compileSdk = COMPILE_SDK @@ -60,7 +60,7 @@ internal fun Project.configureKotlinAndroid( } } -fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { +fun CommonExtension<*, *, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { (this as ExtensionAware).extensions.configure("kotlinOptions", block) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d5a6323..1daeefb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,23 +1,23 @@ [versions] androidDesugarJdkLibs = "2.0.4" -androidGradlePlugin = "8.2.0" +androidGradlePlugin = "8.3.0" androidxAnnotation = "1.7.1" androidxAppCompat = "1.6.1" -androidxComposeBom = "2023.10.01" -androidxComposeCompiler = "1.5.5" -androidxComposeUi = "1.5.4" -androidxComposeUiText = "1.5.4" -androidxLifecycle = "2.6.2" +androidxComposeBom = "2024.02.02" +androidxComposeCompiler = "1.5.7" +androidxComposeUi = "1.6.3" +androidxComposeUiText = "1.6.3" +androidxLifecycle = "2.7.0" androidxTestExtJunit = "1.1.5" androidxTestEspressoCore = "3.5.1" dokkaGradlePlugin = "1.7.20" flowbindingAndroid = "1.2.0" junit4 = "4.13.2" -kotlin = "1.9.20" +kotlin = "1.9.21" kotlinCoroutinesCore = "1.7.3" kotlinCoroutinesAndroid = "1.7.3" kodehighlighter = "4.0.0" -ksp = "1.9.20-1.0.14" +ksp = "1.9.21-1.0.15" zoomlayout = "1.9.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ebe1571..a6a74fa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip From 8ed3b3393d7a9202cc915218549d216fcc3a748f Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 15 Mar 2024 23:37:22 +0100 Subject: [PATCH 56/62] update dependencies --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a6a74fa..5eb588b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip From 41ba750ebee50226c90d9a81632aa0de703d0f3d Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Fri, 15 Mar 2024 23:57:34 +0100 Subject: [PATCH 57/62] update dependencies --- gradle/libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1daeefb..a80a07c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,9 +14,9 @@ dokkaGradlePlugin = "1.7.20" flowbindingAndroid = "1.2.0" junit4 = "4.13.2" kotlin = "1.9.21" -kotlinCoroutinesCore = "1.7.3" -kotlinCoroutinesAndroid = "1.7.3" -kodehighlighter = "4.0.0" +kotlinCoroutinesCore = "1.8.0" +kotlinCoroutinesAndroid = "1.8.0" +kodehighlighter = "4.0.3" ksp = "1.9.21-1.0.15" zoomlayout = "1.9.0" From a47763b8cc82bf0fc05cf630df02ab2cb5cbaf8e Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sat, 16 Mar 2024 16:51:04 +0100 Subject: [PATCH 58/62] refactor --- .../kodeeditor/library/compose/KodeEditor.kt | 133 +++++++++--------- .../kodeeditor/library/compose/LineNumbers.kt | 25 ++-- 2 files changed, 81 insertions(+), 77 deletions(-) diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt index 881827d..bfb7cf8 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/KodeEditor.kt @@ -2,6 +2,7 @@ package de.markusressel.kodeeditor.library.compose import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material.LocalTextStyle @@ -29,71 +30,6 @@ import de.markusressel.kodehighlighter.core.rule.RuleHelper import de.markusressel.kodehighlighter.core.rule.RuleMatch import de.markusressel.kodehighlighter.core.ui.KodeTextField -data class DummyData( - val headingRule: LanguageRule = object : LanguageRule { - override fun findMatches(text: CharSequence): List { - val PATTERN = "^\\s{0,3}#{1,6} .+".toRegex(RegexOption.MULTILINE) - return RuleHelper.findRegexMatches(text, PATTERN) - } - }, - - val dummyRuleBook: LanguageRuleBook = object : LanguageRuleBook { - override fun getRules() = listOf( - headingRule - ) - }, - - val colorScheme: ColorScheme = object : ColorScheme { - override fun getStyles(type: LanguageRule): Set> { - return setOf { SpanStyle(Color(0xFFFF6D00)) } - } - } -) - -private val dummyData = DummyData() - -@Preview -@Composable -private fun KodeEditorPreview() { - var text by remember { - val initialText = """ - # Hello World - Code: `readResourceFileAsText(R.raw.sample_text)` - - ## Secondary headline - - This is a listing: - - * 1 - * 2 - * 3 - - # Code Block - - ``` - This is a code block. - ``` - """.trimIndent() - mutableStateOf(TextFieldValue( - text = initialText - )) - } - - val languageRuleBook by remember { - mutableStateOf(dummyData.dummyRuleBook) - } - val colorScheme by remember { - mutableStateOf(dummyData.colorScheme) - } - - KodeEditor( - text = text, - languageRuleBook = languageRuleBook, - colorScheme = colorScheme, - onValueChange = { text = it } - ) -} - /** * Compose version of the KodeEditorLayout * @@ -206,3 +142,70 @@ fun KodeEditor( } } } + + +private data class DummyData( + val headingRule: LanguageRule = object : LanguageRule { + override fun findMatches(text: CharSequence): List { + val PATTERN = "^\\s{0,3}#{1,6} .+".toRegex(RegexOption.MULTILINE) + return RuleHelper.findRegexMatches(text, PATTERN) + } + }, + + val dummyRuleBook: LanguageRuleBook = object : LanguageRuleBook { + override fun getRules() = listOf( + headingRule + ) + }, + + val colorScheme: ColorScheme = object : ColorScheme { + override fun getStyles(type: LanguageRule): Set> { + return setOf { SpanStyle(Color(0xFFFF6D00)) } + } + } +) + +private val dummyData = DummyData() + +@Preview +@Composable +private fun KodeEditorPreview() { + var text by remember { + val initialText = """ + # Hello World + Code: `readResourceFileAsText(R.raw.sample_text)` + + ## Secondary headline + + This is a listing: + + * 1 + * 2 + * 3 + + # Code Block + + ``` + This is a code block. + ``` + """.trimIndent() + mutableStateOf(TextFieldValue( + text = initialText + )) + } + + val languageRuleBook by remember { + mutableStateOf(dummyData.dummyRuleBook) + } + val colorScheme by remember { + mutableStateOf(dummyData.colorScheme) + } + + KodeEditor( + modifier = Modifier.fillMaxSize(), + text = text, + languageRuleBook = languageRuleBook, + colorScheme = colorScheme, + onValueChange = { text = it } + ) +} diff --git a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt index 7fcc2e4..43e1b30 100644 --- a/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt +++ b/library/src/main/java/de/markusressel/kodeeditor/library/compose/LineNumbers.kt @@ -16,18 +16,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp - -@Preview -@Composable -private fun LineNumbersPreview() { - val text = (1..10).joinToString(separator = "\n", prefix = "Line: ") - LineNumbers( - text = text, - backgroundColor = Color.White, - textColor = Color.Black, - ) -} - @Composable fun LineNumbers( modifier: Modifier = Modifier, @@ -55,3 +43,16 @@ fun LineNumbers( } } + +@Preview(widthDp = 100, heightDp = 500, backgroundColor = 0xFF00FF) +@Composable +private fun LineNumbersPreview() { + val text = (1..10).joinToString(separator = "\n", prefix = "Line: ") + LineNumbers( + text = text, + backgroundColor = Color.White, + textColor = Color.Black, + ) +} + + From d0eacb490e7ae9dbe901bc28dd24148ec5fd4e90 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 14 Jul 2024 15:30:54 +0200 Subject: [PATCH 59/62] update dependencies, add Makefile --- Makefile | 5 +++++ build.gradle.kts | 1 + gradle/libs.versions.toml | 25 ++++++++++++++----------- 3 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cb9a0df --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ + + +build: apk +apk: + ./gradlew assembleDebug diff --git a/build.gradle.kts b/build.gradle.kts index 746bfb0..0abaa27 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,6 +8,7 @@ buildscript { plugins { alias(libs.plugins.android.application) apply false + alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.ksp) apply false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a80a07c..c7009c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,23 +1,23 @@ [versions] androidDesugarJdkLibs = "2.0.4" -androidGradlePlugin = "8.3.0" -androidxAnnotation = "1.7.1" -androidxAppCompat = "1.6.1" -androidxComposeBom = "2024.02.02" +androidGradlePlugin = "8.3.2" +androidxAnnotation = "1.8.0" +androidxAppCompat = "1.7.0" +androidxComposeBom = "2024.06.00" androidxComposeCompiler = "1.5.7" -androidxComposeUi = "1.6.3" -androidxComposeUiText = "1.6.3" -androidxLifecycle = "2.7.0" -androidxTestExtJunit = "1.1.5" -androidxTestEspressoCore = "3.5.1" +androidxComposeUi = "1.6.8" +androidxComposeUiText = "1.6.8" +androidxLifecycle = "2.8.3" +androidxTestExtJunit = "1.2.1" +androidxTestEspressoCore = "3.6.1" dokkaGradlePlugin = "1.7.20" flowbindingAndroid = "1.2.0" junit4 = "4.13.2" -kotlin = "1.9.21" +kotlin = "2.0.0" kotlinCoroutinesCore = "1.8.0" kotlinCoroutinesAndroid = "1.8.0" kodehighlighter = "4.0.3" -ksp = "1.9.21-1.0.15" +ksp = "2.0.0-1.0.22" zoomlayout = "1.9.0" @@ -66,3 +66,6 @@ android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } + +org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } From 75a23d9300e8f8e005f45e30f6d3c97cd9bdfa86 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 14 Jul 2024 15:34:46 +0200 Subject: [PATCH 60/62] remove unused code, fix build --- .../main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt | 5 +---- gradle/libs.versions.toml | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt index 5db304f..4e3aa5a 100644 --- a/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt +++ b/build-logic/convention/src/main/kotlin/de/markusressel/kodeeditor/AndroidCompose.kt @@ -16,16 +16,13 @@ internal fun Project.configureAndroidCompose( commonExtension: CommonExtension<*, *, *, *, *, *>, ) { val libs = extensions.getByType().named("libs") + pluginManager.apply("org.jetbrains.kotlin.plugin.compose") commonExtension.apply { buildFeatures { compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString() - } - dependencies { val bom = libs.findLibrary("androidx-compose-bom").get() add("implementation", platform(bom)) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7009c8..ece2f40 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,6 @@ androidGradlePlugin = "8.3.2" androidxAnnotation = "1.8.0" androidxAppCompat = "1.7.0" androidxComposeBom = "2024.06.00" -androidxComposeCompiler = "1.5.7" androidxComposeUi = "1.6.8" androidxComposeUiText = "1.6.8" androidxLifecycle = "2.8.3" From 615475520cd82a51c15a495321b766fa4d349c2d Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 14 Jul 2024 15:37:56 +0200 Subject: [PATCH 61/62] better Makefile --- Makefile | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cb9a0df..86bd471 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,27 @@ +.PHONY: build +clean: + ./gradlew clean -build: apk -apk: +build: ./gradlew assembleDebug +apk: build + +buildRelease: + ./gradlew assembleRelease + +install: build + adb install ./app/build/outputs/apk/**/*.apk + +installRelease: buildRelease + adb install ./app/build/outputs/apk/**/*.apk + +run: install open + +runRelease: installRelease openRelease + +open: + adb shell am start -n "de.markusressel.kodeeditor.debug/de.markusressel.kodeeditor.demo.ComposeMainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER + +openRelease: + adb shell am start -n "de.markusressel.kodeeditor/de.markusressel.kodeeditor.demo.ComposeMainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER From 6b17123cc69a3d50f37ac0e6f0dcb57097c5b858 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Sun, 14 Jul 2024 15:46:40 +0200 Subject: [PATCH 62/62] cleanup --- app/build.gradle.kts | 9 ++++----- gradle/libs.versions.toml | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 35941b3..8b0fd05 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -25,15 +25,14 @@ dependencies { implementation(libs.kotlin.stdlib.jdk8) implementation(libs.androidx.appcompat) - implementation("com.google.android.material:material:1.9.0") + implementation(libs.material) implementation(libs.androidx.compose.ui) implementation(libs.androidx.compose.material) implementation(libs.androidx.lifecycle.runtime.ktx) - implementation("androidx.activity:activity-compose:1.7.1") + implementation(libs.androidx.activity.compose) - val fuelVersion = "2.3.1" - implementation("com.github.kittinunf.fuel:fuel:$fuelVersion") - implementation("com.github.kittinunf.fuel:fuel-android:$fuelVersion") + implementation(libs.fuel) + implementation(libs.fuel.android) implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.android) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ece2f40..c740164 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,4 +1,5 @@ [versions] +activityCompose = "1.9.0" androidDesugarJdkLibs = "2.0.4" androidGradlePlugin = "8.3.2" androidxAnnotation = "1.8.0" @@ -10,6 +11,7 @@ androidxLifecycle = "2.8.3" androidxTestExtJunit = "1.2.1" androidxTestEspressoCore = "3.6.1" dokkaGradlePlugin = "1.7.20" +fuel = "2.3.1" flowbindingAndroid = "1.2.0" junit4 = "4.13.2" kotlin = "2.0.0" @@ -17,6 +19,7 @@ kotlinCoroutinesCore = "1.8.0" kotlinCoroutinesAndroid = "1.8.0" kodehighlighter = "4.0.3" ksp = "2.0.0-1.0.22" +material = "1.12.0" zoomlayout = "1.9.0" @@ -24,6 +27,7 @@ zoomlayout = "1.9.0" android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" } android-gradle-plugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } androidx-annotation = { group = "androidx.annotation", name = "annotation", version.ref = "androidxAnnotation" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" } @@ -39,6 +43,9 @@ androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecyc dokka-gradle-plugin = { group = "org.jetbrains.dokka", name = "dokka-gradle-plugin", version.ref = "dokkaGradlePlugin" } +fuel = { group = "com.github.kittinunf.fuel", name = "fuel", version.ref = "fuel" } +fuel-android = { group = "com.github.kittinunf.fuel", name = "fuel-android", version.ref = "fuel" } + flowbinding-android = { group = "io.github.reactivecircus.flowbinding", name = "flowbinding-android", version.ref = "flowbindingAndroid" } kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } @@ -52,6 +59,7 @@ ksp-gradle-plugin = { group = "com.google.devtools.ksp", name = "com.google.devt kodehighlighter-core = { group = "com.github.markusressel.KodeHighlighter", name = "core", version.ref = "kodehighlighter" } kodehighlighter-markdown = { group = "com.github.markusressel.KodeHighlighter", name = "markdown", version.ref = "kodehighlighter" } +material = { module = "com.google.android.material:material", version.ref = "material" } zoomlayout = { group = "com.otaliastudios", name = "zoomlayout", version.ref = "zoomlayout" } junit4 = { group = "junit", name = "junit", version.ref = "junit4" }