Skip to content

Commit

Permalink
Add setViewRange function. Rename ILinearAxisModel.
Browse files Browse the repository at this point in the history
  • Loading branch information
gsteckman committed Sep 1, 2024
1 parent 15ac859 commit 32808e9
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 16 deletions.
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,31 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- setViewRange function on LinearAxisModel interface.

### Changed

- Removed minimumMajorTickSpacing from AxisModel interface and added to ILinearAxisModel
- Renamed ILinearAxisModel to LinearAxisModel
- Removed minimumMajorTickSpacing from AxisModel interface and added to LinearAxisModel
- Upgrade Kotlin to 2.0.20
- Upgrade com.android.library to 8.5.2
- Upgrade gradle wrapper to 8.10

### Fixed

- #81 Add coerceAtLeast to rememberIntLinearAxisModel to fix Zoom range limit when range is small

### Removed

- Removed deprecated LinearAxisModel class and rememberLinearAxisModel function

## [0.6.3]

### Fixed

- XYGraph didn't fill all available width when x-axis label intrinsic widths are greater than tick spacing
- XYGraph didn't fill all available width when x-axis label intrinsic widths are greater than tick spacing

## [0.6.2]

Expand All @@ -41,11 +48,13 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.6.1]

### Changed

- VerticalBarPlot scales bar width by number of x-axis major ticks when there is only 1 data point.

## [0.6.0]

### Changed

- Replaced LinearAxisModel (deprecated) with FloatLinearAxisModel
- BulletGraphs can use any linear axis model type

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import io.github.koalaplot.core.util.ExperimentalKoalaPlotApi
import io.github.koalaplot.core.xygraph.Axis
import io.github.koalaplot.core.xygraph.AxisDelegate
import io.github.koalaplot.core.xygraph.AxisStyle
import io.github.koalaplot.core.xygraph.ILinearAxisModel
import io.github.koalaplot.core.xygraph.LinearAxisModel
import io.github.koalaplot.core.xygraph.rememberAxisStyle
import kotlin.math.abs
import kotlin.math.absoluteValue
Expand Down Expand Up @@ -71,7 +71,7 @@ private const val MinRangeShade = 0.99f
*/
@ExperimentalKoalaPlotApi
@BulletGraphDslMarker
public class BulletBuilderScope<T>(private val axisModel: ILinearAxisModel<T>) where T : Comparable<T>, T : Number {
public class BulletBuilderScope<T>(private val axisModel: LinearAxisModel<T>) where T : Comparable<T>, T : Number {
internal class ComparativeMeasure<T>(val value: T, val indicator: @Composable () -> Unit) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import io.github.koalaplot.core.style.KoalaPlotTheme
import io.github.koalaplot.core.util.ExperimentalKoalaPlotApi
import io.github.koalaplot.core.xygraph.ILinearAxisModel
import io.github.koalaplot.core.xygraph.LinearAxisModel
import kotlin.math.roundToInt

/**
Expand Down Expand Up @@ -136,7 +136,7 @@ constructor(
*/
@OptIn(ExperimentalKoalaPlotApi::class)
public fun <T> bullet(
axisModel: ILinearAxisModel<T>,
axisModel: LinearAxisModel<T>,
builder: BulletBuilderScope<T>.() -> Unit
) where T : Comparable<T>, T : Number {
val scope = BulletBuilderScope(axisModel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ public interface TickValues<T> {
* @param T The data type for the axis values.
*/
public interface AxisModel<T> {
/**
* Specifies the minimum spacing for major ticks, in Dp units. Must be greater than 0.
*/
// public val minimumMajorTickSpacing: Dp

/**
* Computes major and minor tick values based on the minimum tick spacing and the overall
* [axisLength].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class DoubleLinearAxisModel(
private val minorTickCount: Int = 4,
private val allowZooming: Boolean = true,
private val allowPanning: Boolean = true,
) : ILinearAxisModel<Double> {
) : LinearAxisModel<Double> {
init {
require(range.endInclusive > range.start) {
"Axis range end (${range.endInclusive}) must be greater than start (${range.start})"
Expand Down Expand Up @@ -194,6 +194,18 @@ public class DoubleLinearAxisModel(
currentRange = newLow..newHi
}

override fun setViewRange(newRange: ClosedRange<Double>) {
if (newRange.endInclusive - newRange.start < zoomRangeLimit) {
val mid = (newRange.endInclusive - newRange.start) / 2.0
currentRange =
(newRange.start - mid).coerceAtLeast(range.start)..(newRange.endInclusive + mid)
.coerceAtMost(range.endInclusive)
} else {
currentRange =
newRange.start.coerceAtLeast(range.start)..newRange.endInclusive.coerceAtMost(range.endInclusive)
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class FloatLinearAxisModel(
private val minorTickCount: Int = 4,
private val allowZooming: Boolean = true,
private val allowPanning: Boolean = true,
) : AxisModel<Float>, ILinearAxisModel<Float> {
) : AxisModel<Float>, LinearAxisModel<Float> {
init {
require(range.endInclusive > range.start) {
"Axis range end (${range.endInclusive}) must be greater than start (${range.start})"
Expand Down Expand Up @@ -195,6 +195,18 @@ public class FloatLinearAxisModel(
currentRange = newLow..newHi
}

override fun setViewRange(newRange: ClosedRange<Float>) {
if (newRange.endInclusive - newRange.start < zoomRangeLimit) {
val mid = (newRange.endInclusive - newRange.start) / 2f
currentRange =
(newRange.start - mid).coerceAtLeast(range.start)..(newRange.endInclusive + mid)
.coerceAtMost(range.endInclusive)
} else {
currentRange =
newRange.start.coerceAtLeast(range.start)..newRange.endInclusive.coerceAtMost(range.endInclusive)
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class IntLinearAxisModel(
private val minorTickCount: Int = 4,
private val allowZooming: Boolean = true,
private val allowPanning: Boolean = true,
) : ILinearAxisModel<Int> {
) : LinearAxisModel<Int> {
init {
require(range.last > range.first) {
"Axis range end (${range.last}) must be greater than start (${range.first})"
Expand Down Expand Up @@ -194,6 +194,17 @@ public class IntLinearAxisModel(
currentRange = newLow..newHi
}

override fun setViewRange(newRange: ClosedRange<Int>) {
if (newRange.endInclusive - newRange.start < zoomRangeLimit) {
val mid = (newRange.endInclusive - newRange.start) / 2
currentRange =
(newRange.start - mid).coerceAtLeast(range.first)..(newRange.endInclusive + mid)
.coerceAtMost(range.last)
} else {
currentRange = newRange.start.coerceAtLeast(range.first)..newRange.endInclusive.coerceAtMost(range.last)
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ internal val TickRatios = listOf(0.1f, 0.2f, 0.5f, 1f, 2f)
internal const val ZoomRangeLimitDefault = 0.2
internal const val MinimumMajorTickIncrementDefault = 0.1f

public interface ILinearAxisModel<T> : AxisModel<T> where T : Comparable<T>, T : Number {
public interface LinearAxisModel<T> : AxisModel<T> where T : Comparable<T>, T : Number {
public val range: ClosedRange<T>
public val minimumMajorTickSpacing: Dp

/**
* Sets the currently viewable range on the axis. This is a more direct alternative to using [pan] and [zoom]
* to set the range of currently viewable values on an axis. The start and end must be within the allowed
* [range] of the axis. If they exceed either limit they will be clamped to the range.
*/
public fun setViewRange(newRange: ClosedRange<T>)
}

internal fun <X, Y> List<Point<X, Y>>.toXList(): List<X> = object : AbstractList<X>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class LongLinearAxisModel(
private val minorTickCount: Int = 4,
private val allowZooming: Boolean = true,
private val allowPanning: Boolean = true,
) : ILinearAxisModel<Long> {
) : LinearAxisModel<Long> {
init {
require(range.last > range.first) {
"Axis range end (${range.last}) must be greater than start (${range.first})"
Expand Down Expand Up @@ -199,6 +199,17 @@ public class LongLinearAxisModel(
currentRange = newLow..newHi
}

override fun setViewRange(newRange: ClosedRange<Long>) {
if (newRange.endInclusive - newRange.start < zoomRangeLimit) {
val mid = (newRange.endInclusive - newRange.start) / 2L
currentRange =
(newRange.start - mid).coerceAtLeast(range.first)..(newRange.endInclusive + mid)
.coerceAtMost(range.last)
} else {
currentRange = newRange.start.coerceAtLeast(range.first)..newRange.endInclusive.coerceAtMost(range.last)
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
Expand Down

0 comments on commit 32808e9

Please sign in to comment.