lets-plot-compose/src/androidMain/kotlin/org/jetbrains/letsPlot/compose/PlotPanelComposeCanvas.kt [141:217]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Box( modifier = finalModifier .weight(1f) // Take the remaining vertical space .fillMaxWidth() // Fill available width .onSizeChanged { newSize -> // Convert logical pixels (from Compose layout) to physical pixels (plot SVG pixels) panelSize = DoubleVector(newSize.width / density, newSize.height / density) } ) { val errMsg = errorMessage if (errMsg != null) { // Show error message BasicTextField( value = errMsg, onValueChange = { }, readOnly = true, textStyle = errorTextStyle, modifier = errorModifier ) } else { // Render the plot LaunchedEffect(panelSize, processedPlotSpec, specOverrideList, preserveAspectRatio) { if (PlotConfig.isFailure(processedPlotSpec)) { errorMessage = PlotConfig.getErrorMessage(processedPlotSpec) return@LaunchedEffect } runCatching { if (panelSize != DoubleVector.ZERO) { val plotSpec = applySpecOverride(processedPlotSpec, specOverrideList).toMutableMap() plotCanvasFigure2.update(plotSpec, fitContainerSize(preserveAspectRatio)) { messages -> if (dispatchComputationMessages) { // do once dispatchComputationMessages = false computationMessagesHandler(messages) } } if (plotFigureModel == null) { plotFigureModel = PlotFigureModel( onUpdateView = { specOverride -> specOverrideList = FigureModelHelper.updateSpecOverrideList( specOverrideList = specOverrideList, newSpecOverride = specOverride ) } ) } plotFigureModel!!.toolEventDispatcher = plotCanvasFigure2.toolEventDispatcher val plotWidth = plotCanvasFigure2.size.x val plotHeight = plotCanvasFigure2.size.y // Calculate centering position in physical pixels // Both panelSize and plot dimensions are in physical pixels plotPosition = DoubleVector( maxOf(0.0, (panelSize.x - plotWidth) / 2.0), maxOf(0.0, (panelSize.y - plotHeight) / 2.0) ) composeMouseEventMapper.setOffset(plotPosition.x.toFloat(), plotPosition.y.toFloat()) redrawTrigger++ // trigger repaint } }.getOrElse { e -> errorMessage = "${e.message}" return@LaunchedEffect } } Canvas( modifier = modifier .fillMaxSize() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lets-plot-compose/src/desktopMain/kotlin/org/jetbrains/letsPlot/compose/PlotPanelComposeCanvas.kt [144:220]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Box( modifier = finalModifier .weight(1f) // Take the remaining vertical space .fillMaxWidth() // Fill available width .onSizeChanged { newSize -> // Convert logical pixels (from Compose layout) to physical pixels (plot SVG pixels) panelSize = DoubleVector(newSize.width / density, newSize.height / density) } ) { val errMsg = errorMessage if (errMsg != null) { // Show error message BasicTextField( value = errMsg, onValueChange = { }, readOnly = true, textStyle = errorTextStyle, modifier = errorModifier ) } else { // Render the plot LaunchedEffect(panelSize, processedPlotSpec, specOverrideList, preserveAspectRatio) { if (PlotConfig.isFailure(processedPlotSpec)) { errorMessage = PlotConfig.getErrorMessage(processedPlotSpec) return@LaunchedEffect } runCatching { if (panelSize != DoubleVector.ZERO) { val plotSpec = applySpecOverride(processedPlotSpec, specOverrideList).toMutableMap() plotCanvasFigure2.update(plotSpec, fitContainerSize(preserveAspectRatio)) { messages -> if (dispatchComputationMessages) { // do once dispatchComputationMessages = false computationMessagesHandler(messages) } } if (plotFigureModel == null) { plotFigureModel = PlotFigureModel( onUpdateView = { specOverride -> specOverrideList = FigureModelHelper.updateSpecOverrideList( specOverrideList = specOverrideList, newSpecOverride = specOverride ) } ) } plotFigureModel!!.toolEventDispatcher = plotCanvasFigure2.toolEventDispatcher val plotWidth = plotCanvasFigure2.size.x val plotHeight = plotCanvasFigure2.size.y // Calculate centering position in physical pixels // Both panelSize and plot dimensions are in physical pixels plotPosition = DoubleVector( maxOf(0.0, (panelSize.x - plotWidth) / 2.0), maxOf(0.0, (panelSize.y - plotHeight) / 2.0) ) composeMouseEventMapper.setOffset(plotPosition.x.toFloat(), plotPosition.y.toFloat()) redrawTrigger++ // trigger repaint } }.getOrElse { e -> errorMessage = "${e.message}" return@LaunchedEffect } } Canvas( modifier = modifier .fillMaxSize() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -