Skip to content
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2023, TeamDev. All rights reserved.
*
* 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
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.examples.shareaware.client

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import org.jetbrains.skia.Point

/**
* Draws an Y axis inside the drawing area.
*
* @param color the color of the axis line
* @param axisWidth the width of the axis line
*/
public fun DrawScope.drawYAxis(
color: Color,
axisWidth: Float = 2f
) {
drawLine(
color = color,
start = Offset(0f, 0f),
end = Offset(0f, size.height),
strokeWidth = axisWidth
)
}

/**
* Draws an X axis inside the drawing area.
*
* @param color the color of the axis line
* @param axisWidth the width of the axis line
*/
public fun DrawScope.drawXAxis(
color: Color,
axisWidth: Float = 2f
) {
drawLine(
color = color,
start = Offset(0f, size.height - 0f),
end = Offset(size.width, size.height - 0f),
strokeWidth = axisWidth
)
}

/**
* Maps a list of points from their original range to pixel coordinates within the drawing area.
*
* @param points the list of points to map
*/
public fun DrawScope.mapToPixelPoints(points: List<Point>): List<Point> {
val minXValue = points.minOf { it.x }
val maxXValue = points.maxOf { it.x }
val minYValue = points.minOf { it.y }
val maxYValue = points.maxOf { it.y }
return points.map {
val x = it.x.mapToDifferentRange(
inMin = minXValue,
inMax = maxXValue,
outMin = 0f,
outMax = size.width
)
val y = it.y.mapToDifferentRange(
inMin = minYValue,
inMax = maxYValue,
outMin = size.height,
outMax = 0f
)
Point(x, y)
}
}

/**
* Remaps a value from one range to another.
*
* @param inMin The minimum value of the original range
* @param inMax The maximum value of the original range
* @param outMin The minimum value of the target range
* @param outMax The maximum value of the target range
Comment on lines +100 to +103

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param inMin The minimum value of the original range
* @param inMax The maximum value of the original range
* @param outMin The minimum value of the target range
* @param outMax The maximum value of the target range
* @param inMin the minimum value of the original range
* @param inMax the maximum value of the original range
* @param outMin the minimum value of the target range
* @param outMax the maximum value of the target range

Also, it might be better to name the parameters as originalMin and targetMin.

*/
private fun Float.mapToDifferentRange(
inMin: Float,
inMax: Float,
outMin: Float,
outMax: Float
): Float = (this - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ private val typography: Typography = Typography(
fontWeight = FontWeight.Normal,
fontFamily = sanFrancisco
),
headlineLarge = TextStyle(
fontSize = 30.sp,
fontWeight = FontWeight.SemiBold,
letterSpacing = 0.5.sp,
fontFamily = sanFrancisco
),
bodyMedium = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.SemiBold,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2023, TeamDev. All rights reserved.
*
* 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
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.examples.shareaware.client.component

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke
import io.spine.examples.shareaware.client.drawXAxis
import io.spine.examples.shareaware.client.drawYAxis
import io.spine.examples.shareaware.client.mapToPixelPoints
import org.jetbrains.skia.Point

/**
* Draws a chart.
*
* @param points chart points
*/
@Composable
public fun Chart(points: List<Point>) {
val axisColor = MaterialTheme.colors.onSecondary
val chartLineColor = MaterialTheme.colors.primary
Canvas(
modifier = Modifier.fillMaxSize()
) {
drawYAxis(axisColor)
drawXAxis(axisColor)
val pixelPoints = mapToPixelPoints(points)
val path = Path()
pixelPoints.forEachIndexed { index, point ->
if (index == 0) {
path.moveTo(point.x, point.y)
} else {
path.lineTo(point.x, point.y)
}
}
drawPath(
path = path,
color = chartLineColor,
style = Stroke(width = 2f)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@

package io.spine.examples.shareaware.client.market

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
Expand All @@ -46,7 +48,6 @@ import androidx.compose.ui.unit.dp
import io.spine.examples.shareaware.client.component.ContainerWithPopup
import io.spine.examples.shareaware.client.component.PopupConfig
import io.spine.examples.shareaware.client.component.PrimaryButton
import io.spine.examples.shareaware.client.share.ShareLogo
import io.spine.examples.shareaware.client.share.SharePrice
import io.spine.examples.shareaware.share.Share
import io.spine.money.Money
Expand Down Expand Up @@ -121,17 +122,51 @@ private fun ShareProfile(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
ShareLogo(share)
ShareInfo(share, previousPrice)
ButtonSection(
share = share,
purchaseModel = purchaseModel
)
}
}

/**
* Displays information about a particular share.
*
* @param share the share to display info about
* @param previousPrice the previous price of the share
*/
@Composable
private fun ShareInfo(share: Share, previousPrice: Money?) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Bottom
) {
Text(
text = share.companyName,
style = MaterialTheme.typography.labelMedium,
style = MaterialTheme.typography.headlineLarge,
modifier = Modifier.padding(top = 10.dp)
)
SharePrice(share.price, previousPrice)
ButtonSection(
share = share,
purchaseModel = purchaseModel
)
}
}

/**
* Displays container purposed for drawing chart inside it.
*
* @param chart the chart to draw inside the container
*/
@Composable
private fun ChartContainer(chart: @Composable () -> Unit) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(250.dp)
.background(MaterialTheme.colorScheme.secondary)
.padding(10.dp)
) {
chart()
}
}

Expand Down