koalaplot / koalaplot-core Goto Github PK
View Code? Open in Web Editor NEWKoala Plot is a Compose Multiplatform based charting and plotting library written in Kotlin
Home Page: https://koalaplot.github.io/
License: MIT License
Koala Plot is a Compose Multiplatform based charting and plotting library written in Kotlin
Home Page: https://koalaplot.github.io/
License: MIT License
Hi there,
I stumbled across your lib when searching for a plot lib for Compose Multiplatform.
There is one question that arises: is there any chance to plot stairs for XY values?
Thanks in advance.
I want to implement vertical and horizontal lines tracking the mouse cursor on the chart.
To do this, a feature that converts the mouse cursor's absolute coordinates into relative coordinates on the chart is needed.
And for this, an API that can determine the size of the chart is necessary.
Hello! I've added lib to commonMain dependencies and it seems works well on Android app.
When I'm trying to build an app via Xcode - it says Build Failed with error:
Could not find "org.jetbrains.kotlin.native.platform.Symbols" in [/Users/vdcast/111/DEV/Projects/MoneyWorksPersonal, /Users/vdcast/.konan/klib, /Users/vdcast/.konan/kotlin-native-prebuilt-macos-x86_64-1.9.10/klib/common, /Users/vdcast/.konan/kotlin-native-prebuilt-macos-x86_64-1.9.10/klib/platform/ios_arm64]
Do I need to add in in Xcode libraries? If yes - how to do it?
Please, help me add it to IOS target correctly, ty!
Here is my build.gradle shared module:
`plugins {
kotlin("multiplatform")
id("com.android.library")
id("org.jetbrains.compose")
id("com.squareup.sqldelight")
}
kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
}
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java).all {
binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework::class.java).all {
export("dev.icerock.moko:mvvm-core:0.16.1")
}
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "shared"
isStatic = true
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.components.resources)
implementation("androidx.datastore:datastore-preferences-core:1.1.0-dev01")
implementation("com.squareup.sqldelight:runtime:1.5.5")
implementation("com.squareup.sqldelight:coroutines-extensions:1.5.5")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("org.jetbrains.kotlinx:atomicfu:0.17.3")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("io.github.koalaplot:koalaplot-core:0.5.2")
}
}
val androidMain by getting {
dependencies {
api("androidx.activity:activity-compose:1.8.0")
api("androidx.appcompat:appcompat:1.6.1")
api("androidx.core:core-ktx:1.12.0")
implementation("com.squareup.sqldelight:android-driver:1.5.5")
}
}
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependencies {
implementation("com.squareup.sqldelight:native-driver:1.5.5")
}
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
}
}
android {
compileSdk = (findProperty("android.compileSdk") as String).toInt()
namespace = "com.vdcast.moneyworkspersonal"
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
sourceSets["main"].res.srcDirs("src/androidMain/res")
sourceSets["main"].resources.srcDirs("src/commonMain/resources")
defaultConfig {
minSdk = (findProperty("android.minSdk") as String).toInt()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
}
sqldelight {
database("AppDatabase") {
packageName = "com.vdcast.moneyworkspersonal.data.database"
sourceFolders = listOf("sqldelight")
}
}
dependencies {
implementation("androidx.compose.material3:material3:1.1.2")
implementation("androidx.core:core:1.10.1")
commonMainApi("dev.icerock.moko:mvvm-core:0.16.1")
commonMainApi("dev.icerock.moko:mvvm-compose:0.16.1")
commonMainApi("dev.icerock.moko:mvvm-flow:0.16.1")
commonMainApi("dev.icerock.moko:mvvm-flow-compose:0.16.1")
}`
and build.gradle project:
buildscript {
dependencies {
classpath("com.android.tools.build:gradle:8.1.2")
classpath("com.squareup.sqldelight:gradle-plugin:1.5.5")
classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.17.3")
}
}
plugins {
kotlin("multiplatform").apply(false)
id("com.android.application").apply(false)
id("com.android.library").apply(false)
id("org.jetbrains.compose").apply(false)
}
allprojects {
apply(plugin = "kotlinx-atomicfu")
}
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
Hello.
I get poor display when there are a lot of pieces of the pie and not enough space to display the labels. For example, 40%, 40% and 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1% , 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%, 1%,
Reproducer:
XYGraph(
xAxisModel = LongLinearAxisModel(
points.autoScaleXRange(),
minorTickCount = 0,
minimumMajorTickIncrement = 100,
),
// ...
where points
is an empty list.
Stacktrace:
Exception in thread "main" java.util.NoSuchElementException
at kotlin.collections.CollectionsKt___CollectionsKt.maxOrThrow(_Collections.kt:1920)
at io.github.koalaplot.core.xygraph.LongLinearAxisModelKt.autoScaleRange(LongLinearAxisModel.kt:262)
at io.github.koalaplot.core.xygraph.LongLinearAxisModelKt.autoScaleXRange(LongLinearAxisModel.kt:302)
at MainKt$App$1$2.invoke(Main.kt:79)
at MainKt$App$1$2.invoke(Main.kt:62)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at io.github.koalaplot.core.ChartLayoutKt.ChartLayout(ChartLayout.kt:56)
at MainKt.App(Main.kt:62)
at ComposableSingletons$MainKt$lambda-5$1.invoke(Main.kt:130)
at ComposableSingletons$MainKt$lambda-5$1.invoke(Main.kt:129)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.ui.awt.ComposeWindow$setContent$5.invoke(ComposeWindow.desktop.kt:156)
at androidx.compose.ui.awt.ComposeWindow$setContent$5.invoke(ComposeWindow.desktop.kt:155)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.ui.awt.WindowContentLayout_desktopKt.WindowContentLayout(WindowContentLayout.desktop.kt:103)
at androidx.compose.ui.awt.ComposeWindowPanel$setContent$3$1.invoke(ComposeWindowPanel.desktop.kt:171)
at androidx.compose.ui.awt.ComposeWindowPanel$setContent$3$1.invoke(ComposeWindowPanel.desktop.kt:170)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248)
at androidx.compose.ui.awt.ComposeWindowPanel$setContent$3.invoke(ComposeWindowPanel.desktop.kt:168)
at androidx.compose.ui.awt.ComposeWindowPanel$setContent$3.invoke(ComposeWindowPanel.desktop.kt:167)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.ui.scene.ComposeContainer$setContent$1$1.invoke(ComposeContainer.desktop.kt:231)
at androidx.compose.ui.scene.ComposeContainer$setContent$1$1.invoke(ComposeContainer.desktop.kt:230)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248)
at androidx.compose.ui.scene.ComposeContainer_desktopKt.ProvideContainerCompositionLocals(ComposeContainer.desktop.kt:335)
at androidx.compose.ui.scene.ComposeContainer_desktopKt.access$ProvideContainerCompositionLocals(ComposeContainer.desktop.kt:1)
at androidx.compose.ui.scene.ComposeContainer$setContent$1.invoke(ComposeContainer.desktop.kt:230)
at androidx.compose.ui.scene.ComposeContainer$setContent$1.invoke(ComposeContainer.desktop.kt:229)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248)
at androidx.compose.ui.scene.BaseComposeScene$setContent$1$2.invoke(BaseComposeScene.skiko.kt:139)
at androidx.compose.ui.scene.BaseComposeScene$setContent$1$2.invoke(BaseComposeScene.skiko.kt:138)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:186)
at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2$1.invoke(Wrapper.skiko.kt:49)
at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2$1.invoke(Wrapper.skiko.kt:48)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:266)
at androidx.compose.ui.platform.Wrapper_skikoKt.provide(Wrapper.skiko.kt:62)
at androidx.compose.ui.platform.Wrapper_skikoKt.access$provide(Wrapper.skiko.kt:1)
at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2.invoke(Wrapper.skiko.kt:48)
at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2.invoke(Wrapper.skiko.kt:47)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:33)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3303)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime(Composer.kt:3236)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:725)
at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:1071)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:633)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:619)
at androidx.compose.ui.platform.Wrapper_skikoKt.setContent(Wrapper.skiko.kt:47)
at androidx.compose.ui.scene.MultiLayerComposeSceneImpl.createComposition(MultiLayerComposeScene.skiko.kt:203)
at androidx.compose.ui.scene.BaseComposeScene.setContent(BaseComposeScene.skiko.kt:138)
at androidx.compose.ui.scene.ComposeSceneMediator$setContent$1.invoke(ComposeSceneMediator.desktop.kt:457)
at androidx.compose.ui.scene.ComposeSceneMediator$setContent$1.invoke(ComposeSceneMediator.desktop.kt:455)
at androidx.compose.ui.scene.ComposeSceneMediator.onComponentAttached(ComposeSceneMediator.desktop.kt:410)
at androidx.compose.ui.scene.ComposeContainer.addNotify(ComposeContainer.desktop.kt:186)
at androidx.compose.ui.awt.ComposeWindowPanel.addNotify(ComposeWindowPanel.desktop.kt:148)
at java.desktop/java.awt.Container.addNotify(Container.java:2804)
at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
at java.desktop/java.awt.Container.addNotify(Container.java:2804)
at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
at java.desktop/java.awt.Container.addNotify(Container.java:2804)
at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
at java.desktop/javax.swing.JRootPane.addNotify(JRootPane.java:729)
at java.desktop/java.awt.Container.addNotify(Container.java:2804)
at java.desktop/java.awt.Window.addNotify(Window.java:791)
at java.desktop/java.awt.Frame.addNotify(Frame.java:495)
at java.desktop/java.awt.Window.pack(Window.java:829)
at androidx.compose.ui.util.Windows_desktopKt.setSizeImpl-6HolHcs(Windows.desktop.kt:116)
at androidx.compose.ui.util.Windows_desktopKt.setSizeSafely-hQcJfNw(Windows.desktop.kt:55)
at androidx.compose.ui.window.Window_desktopKt$Window$5.invoke(Window.desktop.kt:239)
at androidx.compose.ui.window.Window_desktopKt$Window$5.invoke(Window.desktop.kt:176)
at androidx.compose.ui.window.Window_desktopKt$Window$12$1.invoke(Window.desktop.kt:426)
at androidx.compose.ui.window.Window_desktopKt$Window$12$1.invoke(Window.desktop.kt:419)
at androidx.compose.ui.window.AwtWindow_desktopKt$AwtWindow$3.invoke(AwtWindow.desktop.kt:78)
at androidx.compose.ui.window.AwtWindow_desktopKt$AwtWindow$3.invoke(AwtWindow.desktop.kt:76)
at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2$performUpdate$1.invoke(UpdateEffect.desktop.kt:59)
at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2$performUpdate$1.invoke(UpdateEffect.desktop.kt:55)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2.invoke$performUpdate(UpdateEffect.desktop.kt:55)
at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2.invoke(UpdateEffect.desktop.kt:64)
at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2.invoke(UpdateEffect.desktop.kt:47)
at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:82)
at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1295)
at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:984)
at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1005)
at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:1099)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:633)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:619)
at androidx.compose.ui.window.Application_desktopKt$awaitApplication$2$1$2.invokeSuspend(Application.desktop.kt:219)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:741)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Id like to smoothen out the lines of my chart. Unfortunately, this happens when I use cornerPathEffect, which makes sense given that its only applied to the lineStyle. Would it be possible to incorporate it in the AreaStyle as well?
LineStyle(
brush = SolidColor(color),
strokeWidth = 2.dp,
pathEffect = cornerPathEffect(/* 40.dp in the screenshot */),
)
The fix was to add 0.01f
to every value so that none of them were zero ๐คฆ
My charts are in a scrollable column, and currently, they swallow all input events even with enabled = false
.
This means I can't scroll my column when my finger is passing over the chat. it makes for some very awkward scrolling.
So far this is happening for me with BarChart, but not PieChart.
It would be great to get some of the libraries updated:
Kotlin 1.8.0
Compose 1.3.0
Could you support candlestick?
XYAnnotation
places a composable within the XYGraph plot area. This feature is to enable placing a Composable as an annotation along the x-axis/y-axis.
Please vote for this issue by adding a ๐ to help prioritize new features.
When rapidly changing chart data size, the app crashes. I think generateHueColorPalette
gets called too late.
Spam-click Toggle list button to reproduce:
fun main() {
application {
Window(
onCloseRequest = this::exitApplication,
title = "Demo app"
) {
Column {
var showBigList by remember { mutableStateOf(false) }
val data = remember(showBigList) {
List(size = if (showBigList) 100 else 5) { it.toFloat() }
}
Button(
onClick = { showBigList = !showBigList }
) {
Text("Toggle list")
}
PieChart(
values = data
)
}
}
}
}
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: index: 5, size: 5
at kotlin.collections.AbstractList$Companion.checkElementIndex$kotlin_stdlib(AbstractList.kt:108)
at kotlin.collections.builders.ListBuilder.get(ListBuilder.kt:39)
at io.github.koalaplot.core.pie.PieChartKt$PieChart$7.invoke(PieChart.kt:339)
at io.github.koalaplot.core.pie.PieChartKt$PieChart$7.invoke(PieChart.kt:337)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:137)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33)
at io.github.koalaplot.core.pie.PieChartKt$Pie$1$1.invoke(PieChart.kt:397)
at io.github.koalaplot.core.pie.PieChartKt$Pie$1$1.invoke(PieChart.kt:390)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$2.invoke(ComposableLambda.jb.kt:128)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$2.invoke(ComposableLambda.jb.kt:127)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:192)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2557)
at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2828)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3315)
at androidx.compose.runtime.ComposerImpl.recompose$runtime(Composer.kt:3266)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:940)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1155)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:127)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:583)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:551)
at androidx.compose.runtime.BroadcastFrameClock$FrameAwaiter.resume(BroadcastFrameClock.kt:42)
at androidx.compose.runtime.BroadcastFrameClock.sendFrame(BroadcastFrameClock.kt:71)
at androidx.compose.ui.scene.BaseComposeScene.render(BaseComposeScene.skiko.kt:163)
at androidx.compose.ui.scene.ComposeSceneMediator$DesktopSkikoView.onRender(ComposeSceneMediator.desktop.kt:523)
at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:548)
at org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54)
at org.jetbrains.skiko.redrawer.Direct3DRedrawer$frameDispatcher$1.invokeSuspend(Direct3DRedrawer.kt:49)
at org.jetbrains.skiko.redrawer.Direct3DRedrawer$frameDispatcher$1.invoke(Direct3DRedrawer.kt)
at org.jetbrains.skiko.redrawer.Direct3DRedrawer$frameDispatcher$1.invoke(Direct3DRedrawer.kt)
at org.jetbrains.skiko.FrameDispatcher$job$1.invokeSuspend(FrameDispatcher.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.scene.ComposeContainer$DesktopCoroutineExceptionHandler@2b52488f, androidx.compose.runtime.BroadcastFrameClock@5bc6f3a2, StandaloneCoroutine{Cancelling}@7d783f0a, FlushCoroutineDispatcher@635857e4]
I managed to fix this by adding nullability when getting slice color. I found no issues with this workaround:
fun main() {
application {
Window(
onCloseRequest = this::exitApplication,
title = "Demo app"
) {
Column {
var showBigList by remember { mutableStateOf(false) }
val data = remember(showBigList) {
List(size = if (showBigList) 100 else 5) { it.toFloat() }
}
Button(
onClick = { showBigList = !showBigList }
) {
Text("Toggle list")
}
PieChart(
values = data
slice = {
val colors = remember(data.size) { generateHueColorPalette(data.size) }
DefaultSlice(colors.getOrNull(it) ?: Color.Transparent) // Can be null here
}
)
}
}
}
}
Library version: 0.6.0
Compose: 1.6.2 (Multiplatform)
Platform: Windows 10
A scatter plot can be created by using LinePlot
with symbols. This feature adds a variant that is a scatter plot with error bars plotted at each point.
Please vote for this issue by adding a ๐ to help prioritize new features.
I'm not sure of the exact cause yet.
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 1
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at io.github.koalaplot.core.bar.VerticalBarChartKt$VerticalBarChart$4.measure-3p2s80s(VerticalBarChart.kt:144)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:103)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1090)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1086)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2201)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:238)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source)
My compose application is using a dark theme. The axis labels are in black and not really visible. How to change the text color of axis labels?
This looks like an awesome library with a ton of potential!
Im fairly certain that more people will play around with it if its easily accessible through maven central. Please consider publishing it even though the library is in its early stages.
For dynamic data it is important to have time-based axis (preferably based on Kotlinx-datetime Instant
. It requires #63 to work properly.
Hi, it is the Gantt chart planned to be implemented or is possible support it?
I use the LineChartSample with a data set of 500 data points instead of the RainData set. This leads to the x-axis not being displayed correctly. If the number for the label reaches two digits, it is no longer displayed.
`@OptIn(ExperimentalKoalaPlotApi::class)
@composable
@Suppress("MagicNumber")
private fun Chart(title: String) {
ChartLayout(
modifier = paddingMod,
title = { ChartTitle(title) },
legend = { Legend() },
legendLocation = LegendLocation.BOTTOM
) {
syncGraphList()
XYGraph(
xAxisModel = CategoryAxisModel(
GraphData.labels
),
yAxisModel = LinearAxisModel(
-128f..128f,
minimumMajorTickSpacing = 20.dp,
),
xAxisStyle = rememberAxisStyle(
color = Color.White,
majorTickSize = 0.dp,
minorTickSize = 0.dp,
tickPosition = TickPosition.None,
lineWidth = 1.dp,
labelRotation = 0
),
xAxisLabels = { AxisLabel(it, Modifier.absolutePadding(right = 2.dp)) },
xAxisTitle = {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.BottomCenter
) {
AxisTitle("Lรคnge [m]",
modifier = Modifier
.padding(20.dp)
)
}
},
yAxisStyle = rememberAxisStyle(
color = Color.White,
majorTickSize = 0.dp,
minorTickSize = 0.dp,
tickPosition = TickPosition.None,
lineWidth = 1.dp,
labelRotation = 0
),
yAxisLabels = {
AxisLabel(it.toString(), Modifier.absolutePadding(right = 2.dp))
},
yAxisTitle = {
Box(
modifier = Modifier.fillMaxHeight(),
contentAlignment = Alignment.TopStart
) {
AxisTitle(
"Einheit (?)",
modifier = Modifier.rotateVertically(VerticalRotation.COUNTER_CLOCKWISE)
.padding(bottom = padding)
)
}
},
horizontalMajorGridLineStyle = KoalaPlotTheme.axis.majorGridlineStyle,
horizontalMinorGridLineStyle = KoalaPlotTheme.axis.minorGridlineStyle,
verticalMajorGridLineStyle = KoalaPlotTheme.axis.majorGridlineStyle,
verticalMinorGridLineStyle = KoalaPlotTheme.axis.minorGridlineStyle,
) {
GraphData.data.entries.sortedBy { it.key }.forEach { (channel, labels) ->
var points = labels.mapIndexed { index, d ->
DefaultPoint(GraphData.labels[index], d.toFloat())
}
chart(
channel,
points,
)
}
}
}
}
@OptIn(ExperimentalKoalaPlotApi::class)
@composable
private fun XYGraphScope<String, Float>.chart(
channel: String,
data: List<DefaultPoint<String, Float>>,
) {
LinePlot(
data = data,
lineStyle = LineStyle(
brush = SolidColor(colorMap[channel] ?: Color.Black),
strokeWidth = 2.dp
),
symbol = { point ->
Symbol(
shape = CircleShape,
size = 2.dp,
fillBrush = SolidColor(colorMap[channel] ?: Color.Black),
modifier = Modifier.then(
Modifier.hoverableElement {
HoverSurface { Text(point.y.toString()) }
}
)
)
}
)
}`
Please vote for this issue by adding a ๐ to help prioritize new features.
Add the capability to add a secondary Y-axis to an XYGraph, displayed on the right side of the plot area.
Please vote for this issue by adding a ๐ to help prioritize new features.
First thanks a lot for this great library.
I am struggling a bit to show a VerticalBarChart with long labels on the x-axis. Spread sheet applications like Excel or Google Sheets offer to show the labels in an rotated angle so that the labels do not overlap. It would be a quite nice enhancement for this library as well. I tried to achieve this on my own without changing the source code of this library but failed. While i was able to rotate and position the labels correctly, i did not achieve change the inner dimensions of the Text composable itself, so that the text wraps even there would be enough space to render the labels without soft wrap.
This screenshot shows how my intended chart is shown in google sheets.
Version: 0.6.0-dev2
I still got ArithmeticException, not sure where it comes from. The exception is not always throwing.
Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException: / by zero
at io.github.koalaplot.core.xygraph.ChartAreas.xTickSpacing(XYGraph.kt:292)
at io.github.koalaplot.core.xygraph.ChartAreas.withComputedXAxisLabelAreas(XYGraph.kt:303)
at io.github.koalaplot.core.xygraph.XYGraphKt.optimizeGraphSize-m8Kt_7k(XYGraph.kt:422)
at io.github.koalaplot.core.xygraph.XYGraphKt.access$optimizeGraphSize-m8Kt_7k(XYGraph.kt:1)
at io.github.koalaplot.core.xygraph.XYAxisMeasurePolicy.measure-3p2s80s(XYGraph.kt:441)
at io.github.koalaplot.core.xygraph.XYGraphKt$XYGraph$1$1.invoke-0kLqBqw(XYGraph.kt:169)
at io.github.koalaplot.core.xygraph.XYGraphKt$XYGraph$1$1.invoke(XYGraph.kt:98)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:709)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at io.github.koalaplot.core.util.HoverableElementAreaKt$HoverableElementArea$2$1.measure-3p2s80s(HoverableElementArea.kt:85)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.RowColumnMeasurementHelper.measureWithoutPlacing-_EkL_-Y(RowColumnMeasurementHelper.kt:172)
at androidx.compose.foundation.layout.RowColumnMeasurePolicy.measure-3p2s80s(RowColumnImpl.kt:73)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.RowColumnMeasurementHelper.measureWithoutPlacing-_EkL_-Y(RowColumnMeasurementHelper.kt:112)
at androidx.compose.foundation.layout.RowColumnMeasurePolicy.measure-3p2s80s(RowColumnImpl.kt:73)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.foundation.layout.SizeNode.measure-3p2s80s(Size.kt:838)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.RowColumnMeasurementHelper.measureWithoutPlacing-_EkL_-Y(RowColumnMeasurementHelper.kt:112)
at androidx.compose.foundation.layout.RowColumnMeasurePolicy.measure-3p2s80s(RowColumnImpl.kt:73)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.foundation.ScrollingLayoutNode.measure-3p2s80s(Scroll.kt:394)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.foundation.layout.FillNode.measure-3p2s80s(Size.kt:699)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1145)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1136)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.onlyRemeasureIfScheduled(MeasureAndLayoutDelegate.kt:598)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:624)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:631)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtree(MeasureAndLayoutDelegate.kt:587)
at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.forceMeasureTheSubtree(RootNodeOwner.skiko.kt:308)
at androidx.compose.ui.node.Owner.forceMeasureTheSubtree$default(Owner.kt:239)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:632)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at org.jetbrains.compose.splitpane.DesktopSplitPaneKt$SplitPane$5.measure-3p2s80s(DesktopSplitPane.kt:100)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1145)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1136)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.onlyRemeasureIfScheduled(MeasureAndLayoutDelegate.kt:598)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:624)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtree(MeasureAndLayoutDelegate.kt:587)
at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.forceMeasureTheSubtree(RootNodeOwner.skiko.kt:308)
at androidx.compose.ui.node.Owner.forceMeasureTheSubtree$default(Owner.kt:239)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:632)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at org.jetbrains.compose.splitpane.DesktopSplitPaneKt$SplitPane$5.measure-3p2s80s(DesktopSplitPane.kt:100)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1145)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1136)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:491)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:377)
at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.measureAndLayout(RootNodeOwner.skiko.kt:290)
at androidx.compose.ui.node.RootNodeOwner.measureAndLayout(RootNodeOwner.skiko.kt:187)
at androidx.compose.ui.scene.MultiLayerComposeSceneImpl.measureAndLayout(MultiLayerComposeScene.skiko.kt:247)
at androidx.compose.ui.scene.BaseComposeScene.doLayout(BaseComposeScene.skiko.kt:225)
at androidx.compose.ui.scene.BaseComposeScene.access$doLayout(BaseComposeScene.skiko.kt:51)
at androidx.compose.ui.scene.BaseComposeScene.render(BaseComposeScene.skiko.kt:164)
at androidx.compose.ui.scene.ComposeSceneMediator$DesktopSkikoView.onRender(ComposeSceneMediator.desktop.kt:522)
at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:548)
at org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54)
at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invokeSuspend(MetalRedrawer.kt:82)
at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invoke(MetalRedrawer.kt)
at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invoke(MetalRedrawer.kt)
at org.jetbrains.skiko.FrameDispatcher$job$1.invokeSuspend(FrameDispatcher.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@3a24894b, SwingDispatcher@773f7baa]
First of all thanks for the great work on Koalaplot, i love it!.
i've had this wiered behaviour with snackbar when koalaplot library is added to the project, the snackbar showes only once and cannot be shown the second time calling 'showsnackbar' function.
effected targets:
here are the steps to reproduce the issue:
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import kotlinx.coroutines.launch
@Composable
fun App() {
MaterialTheme {
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
var x by remember { mutableStateOf(1) }
Scaffold(modifier = Modifier,
snackbarHost = { SnackbarHost(snackbarHostState) }) {
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Button(onClick = {
scope.launch {
snackbarHostState.showSnackbar("Snackbar shown this many times: $x")
x++
}
}) {
Text("Show snackbar!")
}
}
}
}
}
if you remove the koalaplot library and sync then run the snackbar will be shown normally.
Right now MaterialTheme
references material 2, would probably be a good idea to switch to material 3.
Please vote for this issue by adding a ๐ to help prioritize new features.
I'm assuming inside the chart library you use Subcompose? Is there a recommended way to use the charts inside of a widget that grows to match its parent? (Flow layouts, lists, etc).
Using it inside a flow layout produces the following:
java.lang.IllegalStateException: Asking for intrinsic measurements of SubcomposeLayout layouts is not supported. This includes components that are built on top of SubcomposeLayout, such as lazy lists, BoxWithConstraints, TabRow, etc
The GitHub repository https://github.com/AAkira/Kotlin-Multiplatform-Libraries provides an overview of kotlin multiplatform libraries. I think KoalaPlot should be part of it :)
Hi! And thanks for your Compose Multiplatform graph library, it's been great for rendering graphs on my Android/iOS app!
I have a view where the user can cycle through different periods, and I update the rendered data directly from old data to new data, retaining the same composable renderers. I noticed that while updating data, the graph would just keep on showing the old values. I traced the problem to the file io.github.koalaplot.core.bar.VerticalBarPlot.kt
, line 113:
@Composable
public fun <X, Y, E : VerticalBarPlotEntry<X, Y>> XYGraphScope<X, Y>.VerticalBarPlot(
data: List<E>,
modifier: Modifier = Modifier,
bar: @Composable BarScope.(index: Int) -> Unit,
barWidth: Float = 0.9f,
animationSpec: AnimationSpec<Float> = KoalaPlotTheme.animationSpec
) {
val dataAdapter = remember {
EntryToGroupedEntryListAdapter(data)
}
// Delegate to the GroupedVerticalBarPlot - non-grouped is like grouped but with only 1 group per x-axis position
GroupedVerticalBarPlot(
...
)
}
There, the dataAdapter
initialization should be changed to val dataAdapter = remember(data) { ... }
so that it is updated when the underlying data changes. Or at least by duplicating your code structure and changing that fixed the issue for me...
publishToMavenLocal
on a Mac only publishes iOS artifacts. I expect there are other artifacts like common or jvm.
I have tried several chart libraries on android but I didn't find the horizontal scroll axis feature like in the video, really appreciate if there is such a feature in this library
It would be valuable to have snippets & tiny samples directly available in the repository and help on the features discoverability
Hi, is there plan to support Wasm target?
I got an exception when trying to display a XYGraph. I thought it was related to empty data, so I ensure there are some data but still in vain. How to avoid errors to display the chart correctly?
Version: 0.5.2
Target Platform: Desktop
Stacktrace:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Minimum tick spacing must be greater than 0 and less than or equal to 1
at io.github.koalaplot.core.xygraph.LinearAxisModel.computeMajorTickSpacing(LinearAxisModel.kt:104)
at io.github.koalaplot.core.xygraph.LinearAxisModel.computeMajorTickValues(LinearAxisModel.kt:74)
at io.github.koalaplot.core.xygraph.LinearAxisModel.computeTickValues-0680j_4(LinearAxisModel.kt:92)
at io.github.koalaplot.core.xygraph.AxisDelegate$Companion.createAxis-eqLRuRQ(AxisDelegate.kt:95)
at io.github.koalaplot.core.xygraph.AxisDelegate$Companion.createVerticalAxis-wH6b6FI(AxisDelegate.kt:82)
at io.github.koalaplot.core.xygraph.XYGraphKt$XYGraph$1$1.invoke-0kLqBqw(XYGraph.kt:119)
at io.github.koalaplot.core.xygraph.XYGraphKt$XYGraph$1$1.invoke(XYGraph.kt:98)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:709)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at io.github.koalaplot.core.util.HoverableElementAreaKt$HoverableElementArea$2$1.measure-3p2s80s(HoverableElementArea.kt:85)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1145)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1136)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.onlyRemeasureIfScheduled(MeasureAndLayoutDelegate.kt:598)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:624)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:631)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:631)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:631)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:631)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:631)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtree(MeasureAndLayoutDelegate.kt:587)
at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.forceMeasureTheSubtree(RootNodeOwner.skiko.kt:308)
at androidx.compose.ui.node.Owner.forceMeasureTheSubtree$default(Owner.kt:239)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:632)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at org.jetbrains.compose.splitpane.DesktopSplitPaneKt$SplitPane$5.measure-3p2s80s(DesktopSplitPane.kt:100)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1145)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1136)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.onlyRemeasureIfScheduled(MeasureAndLayoutDelegate.kt:598)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:624)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtree(MeasureAndLayoutDelegate.kt:587)
at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.forceMeasureTheSubtree(RootNodeOwner.skiko.kt:308)
at androidx.compose.ui.node.Owner.forceMeasureTheSubtree$default(Owner.kt:239)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:632)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at org.jetbrains.compose.splitpane.DesktopSplitPaneKt$SplitPane$5.measure-3p2s80s(DesktopSplitPane.kt:100)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1145)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1136)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:491)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:377)
at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.measureAndLayout(RootNodeOwner.skiko.kt:290)
at androidx.compose.ui.node.RootNodeOwner.measureAndLayout(RootNodeOwner.skiko.kt:187)
at androidx.compose.ui.scene.MultiLayerComposeSceneImpl.measureAndLayout(MultiLayerComposeScene.skiko.kt:247)
at androidx.compose.ui.scene.BaseComposeScene.doLayout(BaseComposeScene.skiko.kt:225)
at androidx.compose.ui.scene.BaseComposeScene.access$doLayout(BaseComposeScene.skiko.kt:51)
at androidx.compose.ui.scene.BaseComposeScene.render(BaseComposeScene.skiko.kt:164)
at androidx.compose.ui.scene.ComposeSceneMediator$DesktopSkikoView.onRender(ComposeSceneMediator.desktop.kt:490)
at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:548)
at org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54)
at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invokeSuspend(MetalRedrawer.kt:82)
at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invoke(MetalRedrawer.kt)
at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invoke(MetalRedrawer.kt)
at org.jetbrains.skiko.FrameDispatcher$job$1.invokeSuspend(FrameDispatcher.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@570805d2, SwingDispatcher@6d583e10]
Reproducer:
ChartLayout(title = { AppText("Latencies over Time (95%)") }) {
latenciesMsOverTime.takeIf { it.size >= 2 }?.let { latenciesMsOverTime ->
XYGraph(
xAxisModel = CategoryAxisModel(
latenciesMsOverTime.keys.toList().ifEmpty { listOf(KInstant.now().toMilliseconds()) }),
yAxisModel = LinearAxisModel(
range = 0f..6000f,
),
xAxisLabels = { KZonedInstant(it, KZoneOffset.local()).format("HH:mm:ss") },
xAxisTitle = "Time",
yAxisTitle = "Latency (ms)",
) {
latenciesMsOverTime.forEach { (timestamp, result) ->
DefaultPoint(timestamp, result.at95Percent)
}
}
}
}
Hi, it looks like version 0.5.2
is built with Compose Multiplatform 1.6.0-beta01
which causes following issue when updating to 1.6.0
Please vote for this issue by adding a ๐ to help prioritize new features.
The graph generation animation in the bar plots currently always starts from the bottom of the graph.
This looks weird if the Y axis zero point is not at the bottom of the graph. For example if you want to show positive and negative values, with the bars attaching to 0.
It would be great if we could set the Y position the bars are built up/down from.
I really dig the hoverable functionality on desktop. It would be sweet if something similar was available for Android and iOS.
Im not sure which approach is most fitting for mobile, but I do love the tactile feeling of scrubbing through a graph and immediately seeing the closest value highlighted - either just above my finger, or at the TopCenter of the graph.
This seems to happen when I have bars with very low values, like 0 or 1? not sure, trying to narrow it down.
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Cannot round NaN value.
at kotlin.math.MathKt__MathJVMKt.roundToInt(MathJVM.kt:1165)
at io.github.koalaplot.core.bar.VerticalBarChartKt$VerticalBarChart$4$measure$1.invoke(VerticalBarChart.kt:183)
at io.github.koalaplot.core.bar.VerticalBarChartKt$VerticalBarChart$4$measure$1.invoke(VerticalBarChart.kt:164)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
Currently it is not possible to automatically re-scale axis to match data change in case of dynamic data. It would be nice to have this option in Axis API.
If you have a pie chart where every item has a value of zero, it will crash.
I'm seeing a bunch of ReplaceWith
though the class it wants me to change to doesn't seem to exist
Example:
However if I search the codebase for BarPlotEntry
(https://github.com/search?q=repo%3AKoalaPlot%2Fkoalaplot-core%20BarPlotEntry&type=code) it doesn't exist. There is VerticalBarPlotEntry
which seems to the right one?
Theres a lot of these such as FloatStackedAreaPlotEntry
(
There is also no implementation of StackedAreaPlotEntry
, Float or otherwise
Hi, i have pulled the sample and check on my android device. It seems great. The rainfall data looks great.
Also I want to know if there is any features of scrolling horizontally LineChart so when there is more data says for like 30 days. The ui may not look congested. Jan feb mar... seems congested. User will scroll horizontally and gap will be maintained to view full month.
also say if i have market price of 30 days which gives 30 data (not scrollable)
i want to show the month horizontally say jan1 jan5 feb15 feb30 (fixed) and load the plotting line in the middle for that 30 days price. Can we do this? Please provide the hint.
i mean to say the months can load like jan,apr,sep,dec (only 4 with the gap)and all plotting will be done inbetween.
val months =
listOf("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
// if i change months to only size of 5 it crases array out of bound.
val rainfall = buildMap {
put(
"New York City",
listOf(83.6, 78.8, 98.5, 93.4, 106.0, 84.5, 105.0, 104.3, 91.2, 83.5, 106.6, 92.3)
)
Also, i wonder if there is official api documentation and features. Please provide the link.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.