.() -> Unit = {} + ): UnrestrictedVerticalAxis
= Builder
().apply(block).build() + } +} diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/data/CartesianValueFormatter.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/data/CartesianValueFormatter.kt index e5a803e8f..9b1efc61d 100644 --- a/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/data/CartesianValueFormatter.kt +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/data/CartesianValueFormatter.kt @@ -33,6 +33,12 @@ public fun interface CartesianValueFormatter { verticalAxisPosition: AxisPosition.Vertical?, ): CharSequence +// public fun format( +// value: Number, +// chartValues: ChartValues, +// verticalAxisPosition: AxisPosition.Vertical?, +// ): CharSequence = format(value.toFloat(), chartValues, verticalAxisPosition) + /** Houses [CartesianValueFormatter] factory functions. */ public companion object { private class Decimal(private val decimalFormat: DecimalFormat) : CartesianValueFormatter { diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/LineCartesianLayer.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/LineCartesianLayer.kt index e4c897253..f3d42f85b 100644 --- a/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/LineCartesianLayer.kt +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/LineCartesianLayer.kt @@ -171,7 +171,7 @@ public open class LineCartesianLayer( } /** Draws the line background. */ - public fun drawBackgroundLine( + public open fun drawBackgroundLine( context: DrawContext, bounds: RectF, zeroLineYFraction: Float, diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/spec/SplitLineSpec.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/spec/SplitLineSpec.kt new file mode 100644 index 000000000..b19b989a2 --- /dev/null +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/cartesian/layer/spec/SplitLineSpec.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2024 by Patryk Goworowski and Patrick Michalik. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.patrykandpatrick.vico.core.cartesian.layer.spec + +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF +import androidx.annotation.FloatRange +import com.patrykandpatrick.vico.core.cartesian.DefaultPointConnector +import com.patrykandpatrick.vico.core.cartesian.data.CartesianValueFormatter +import com.patrykandpatrick.vico.core.cartesian.layer.LineCartesianLayer +import com.patrykandpatrick.vico.core.common.Defaults +import com.patrykandpatrick.vico.core.common.DrawContext +import com.patrykandpatrick.vico.core.common.VerticalPosition +import com.patrykandpatrick.vico.core.common.component.Component +import com.patrykandpatrick.vico.core.common.component.TextComponent +import com.patrykandpatrick.vico.core.common.copy +import com.patrykandpatrick.vico.core.common.shader.DynamicShader +import com.patrykandpatrick.vico.core.common.updateBounds + +/** + * TODO + */ +public class SplitLineSpec( + shader: DynamicShader, + thicknessDp: Float = Defaults.LINE_SPEC_THICKNESS_DP, + public val backgroundShaderFirst: DynamicShader? = null, + public val backgroundShaderSecond: DynamicShader? = null, + cap: Paint.Cap = Paint.Cap.ROUND, + point: Component? = null, + pointSizeDp: Float = Defaults.POINT_SIZE, + dataLabel: TextComponent? = null, + dataLabelVerticalPosition: VerticalPosition = VerticalPosition.Top, + dataLabelValueFormatter: CartesianValueFormatter = CartesianValueFormatter.decimal(), + dataLabelRotationDegrees: Float = 0f, + pointConnector: PointConnector = DefaultPointConnector(), + @FloatRange(from = 0.0, to = 1.0) public val xSplitFraction: Float = 1f, +) : LineCartesianLayer.LineSpec( + shader = shader, + thicknessDp = thicknessDp, + backgroundShader = backgroundShaderFirst, + cap = cap, + point = point, + pointSizeDp = pointSizeDp, + dataLabel = dataLabel, + dataLabelVerticalPosition = dataLabelVerticalPosition, + dataLabelValueFormatter = dataLabelValueFormatter, + dataLabelRotationDegrees = dataLabelRotationDegrees, + pointConnector = pointConnector, +) { + + override fun drawBackgroundLine( + context: DrawContext, + bounds: RectF, + zeroLineYFraction: Float, + path: Path, + opacity: Float, + ) { + backgroundShader = backgroundShaderFirst + when { + xSplitFraction <= 0f -> { + backgroundShader = backgroundShaderSecond + super.drawBackgroundLine(context, bounds, zeroLineYFraction, path, opacity) + backgroundShader = backgroundShaderFirst + return + } + xSplitFraction >= 1 -> { + super.drawBackgroundLine(context, bounds, zeroLineYFraction, path, opacity) + return + } + } + + val firstBounds = RectF( + /* left = */ bounds.left, + /* top = */ bounds.top, + /* right = */ bounds.right * xSplitFraction, + /* bottom = */ bounds.bottom, + ) + val secondBounds = RectF( + /* left = */ bounds.right * xSplitFraction, + /* top = */ bounds.top, + /* right = */ bounds.right, + /* bottom = */ bounds.bottom, + ) + super.drawBackgroundLine(context, firstBounds, zeroLineYFraction, path, opacity) + backgroundShader = backgroundShaderSecond + super.drawBackgroundLine(context, secondBounds, zeroLineYFraction, path, opacity) + backgroundShader = backgroundShaderFirst + } +} diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/common/component/UnboundedLineComponent.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/common/component/UnboundedLineComponent.kt new file mode 100644 index 000000000..32c842baf --- /dev/null +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/common/component/UnboundedLineComponent.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2024 by Patryk Goworowski and Patrick Michalik. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.patrykandpatrick.vico.core.common.component + +import android.graphics.Color +import com.patrykandpatrick.vico.core.common.Defaults +import com.patrykandpatrick.vico.core.common.Dimensions +import com.patrykandpatrick.vico.core.common.DrawContext +import com.patrykandpatrick.vico.core.common.shader.DynamicShader +import com.patrykandpatrick.vico.core.common.shape.Shape + +/** + * This class represents an unbounded line component. It extends the LineComponent class and + * provides additional functionality for drawing vertical and horizontal lines with additional + * drawing space. + * + * @property color the background color. + * @property thicknessDp the thickness of the line. + * @property shape the [Shape] to use for the line. + * @property dynamicShader an optional [DynamicShader] to apply to the line. + * @property margins the margins of the line. + * @property strokeWidthDp the stroke width. + * @property strokeColor the stroke color. + * @param verticalAddDrawSpaceDp Additional vertical drawing space for the line component in density-independent pixels (dp). + * @param horizontalAddDrawSpaceDp Additional horizontal drawing space for the line component in density-independent pixels (dp). + * + * @see LineComponent + * @see Shape + * @see DynamicShader + * @see Dimensions + */ +public class UnboundedLineComponent( + color: Int, + thicknessDp: Float = Defaults.LINE_COMPONENT_THICKNESS_DP, + shape: Shape = Shape.Rectangle, + dynamicShader: DynamicShader? = null, + margins: Dimensions = Dimensions.Empty, + strokeWidthDp: Float = 0f, + strokeColor: Int = Color.TRANSPARENT, + protected val verticalAddDrawSpaceDp: Float = 0f, + protected val horizontalAddDrawSpaceDp: Float = 0f, +) : LineComponent( + color = color, + thicknessDp = thicknessDp, + shape = shape, + dynamicShader = dynamicShader, + margins = margins, + strokeWidthDp = strokeWidthDp, + strokeColor = strokeColor, +) { + + override fun drawVertical( + context: DrawContext, + top: Float, + bottom: Float, + centerX: Float, + thicknessScale: Float, + opacity: Float, + ) { + with(context) { + draw( + context, + left = centerX - thicknessDp.pixels * thicknessScale / 2, + top = top - verticalAddDrawSpaceDp, + right = centerX + thicknessDp.pixels * thicknessScale / 2, + bottom = bottom + verticalAddDrawSpaceDp, + opacity = opacity, + ) + } + } + + override fun drawHorizontal( + context: DrawContext, + left: Float, + right: Float, + centerY: Float, + thicknessScale: Float, + opacity: Float, + ) { + with(context) { + draw( + context, + left = left - horizontalAddDrawSpaceDp, + top = centerY - thicknessDp.pixels * thicknessScale / 2, + right = right + horizontalAddDrawSpaceDp, + bottom = centerY + thicknessDp.pixels * thicknessScale / 2, + opacity = opacity, + ) + } + } + +}