Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log color #72

Merged
merged 17 commits into from
Jul 19, 2022
3 changes: 2 additions & 1 deletion src/main/java/ru/nucodelabs/data/ves/ExperimentalData.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ru.nucodelabs.data.ves

import jakarta.validation.constraints.DecimalMin
import jakarta.validation.constraints.Max
import jakarta.validation.constraints.Min
import jakarta.validation.constraints.Positive
Expand All @@ -19,7 +20,7 @@ data class ExperimentalData(
@field:Positive val mn2: Double,
@field:Min(0) val amperage: Double,
@field:Min(0) val voltage: Double,
@field:Min(1) val resistanceApparent: Double = rhoA(ab2, mn2, amperage, voltage),
@field:DecimalMin("0.1") val resistanceApparent: Double = rhoA(ab2, mn2, amperage, voltage),
@field:Min(0) @Max(100) val errorResistanceApparent: Double = 5.0,
val isHidden: Boolean = false
)
2 changes: 1 addition & 1 deletion src/main/java/ru/nucodelabs/gem/app/pref/UIPreferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package ru.nucodelabs.gem.app.pref
val VES_CURVES_LEGEND_VISIBLE = Preference("VES_CURVES_LEGEND", false)

@JvmField
val COLOR_MIN_VALUE = Preference("COLOR_MIN_VALUE", 1.0)
val COLOR_MIN_VALUE = Preference("COLOR_MIN_VALUE", 0.1)

@JvmField
val COLOR_MAX_VALUE = Preference("COLOR_MAX_VALUE", 100_000.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PropertyDelegate<T>(val fxProperty: Property<T>) : ReadWriteProperty<Any,
/**
* Binds this property to an observable, automatically unbinding it before if already bound.
*/
infix fun <T> Property<T>.rebindTo(observable: ObservableValue<T>) {
infix fun <T> Property<T>.bindTo(observable: ObservableValue<T>) {
unbind()
bind(observable)
}
Expand Down
96 changes: 67 additions & 29 deletions src/main/java/ru/nucodelabs/gem/view/charts/ColorAxisController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import javafx.event.EventHandler
import javafx.fxml.FXML
import javafx.scene.chart.XYChart.Data
import javafx.scene.chart.XYChart.Series
import javafx.scene.control.CheckBox
import javafx.scene.control.ContextMenu
import javafx.scene.control.Spinner
import javafx.scene.control.SpinnerValueFactory
import javafx.scene.control.TextFormatter
import javafx.scene.input.ContextMenuEvent
import javafx.scene.layout.VBox
import javafx.stage.Stage
import javafx.stage.StageStyle
import javafx.util.StringConverter
import ru.nucodelabs.gem.app.pref.*
import ru.nucodelabs.gem.extensions.fx.*
import ru.nucodelabs.gem.extensions.fx.decimalFilter
import ru.nucodelabs.gem.extensions.fx.isValidBy
import ru.nucodelabs.gem.extensions.fx.observableListOf
Expand All @@ -22,13 +25,14 @@ import ru.nucodelabs.gem.view.color.ColorMapper
import ru.nucodelabs.gem.view.control.chart.NucodeNumberAxis
import ru.nucodelabs.gem.view.control.chart.PolygonChart
import ru.nucodelabs.gem.view.control.chart.limitTickLabelsWidth
import ru.nucodelabs.gem.view.control.chart.rangeBinding
import ru.nucodelabs.gem.view.control.chart.log.LogarithmicAxis
import java.net.URL
import java.text.DecimalFormat
import java.util.*
import java.util.prefs.Preferences
import javax.inject.Inject


class ColorAxisController @Inject constructor(
private val colorMapper: ColorMapper,
private val fxPreferences: FXPreferences,
Expand All @@ -37,9 +41,12 @@ class ColorAxisController @Inject constructor(
private val decimalFormat: DecimalFormat
) : AbstractController() {

private val minAndMaxRange = 0.0..100_000.0
private val minAndMaxRange = 0.1..100_000.0
private val segmentsRange = 2..100

@FXML
private lateinit var root: VBox

@FXML
private lateinit var configWindow: Stage

Expand All @@ -52,31 +59,54 @@ class ColorAxisController @Inject constructor(
@FXML
private lateinit var numberOfSegmentsSpinner: Spinner<Int>

@FXML
private lateinit var isLogChkBox: CheckBox

@FXML
private lateinit var ctxMenu: ContextMenu

@FXML
private lateinit var yAxis: NucodeNumberAxis
private lateinit var linearYAxis: NucodeNumberAxis

@FXML
private lateinit var chart: PolygonChart
private lateinit var logYAxis: LogarithmicAxis

@FXML
private lateinit var linearChart: PolygonChart

@FXML
private lateinit var logChart: PolygonChart

override val stage: Stage?
get() = chart.scene.window as Stage?
get() = root.scene.window as Stage?

override fun initialize(location: URL?, resources: ResourceBundle?) {
colorMapper.minValueProperty().addListener { _, _, _ -> update() }
colorMapper.maxValueProperty().addListener { _, _, _ -> update() }
colorMapper.numberOfSegmentsProperty().addListener { _, _, _ -> update() }
colorMapper.logScaleProperty().addListener { _, _, _ -> update() }

linearChart.data = observableListOf()

setupControls()
setupAxis()
setupCharts()
setupAxes()
update()
}

private fun setupAxis() {
yAxis.tickLabelFormatter = stringConverter
yAxis.tickUnitProperty().bind(yAxis.rangeBinding().divide(colorMapper.numberOfSegmentsProperty()))
yAxis.limitTickLabelsWidth(35.0)
private fun setupAxes() {
linearYAxis.lowerBoundProperty() bindTo colorMapper.minValueProperty()
linearYAxis.upperBoundProperty() bindTo colorMapper.maxValueProperty()

logYAxis.lowerBoundProperty() bindTo linearYAxis.lowerBoundProperty()
logYAxis.upperBoundProperty() bindTo linearYAxis.upperBoundProperty()

linearYAxis.tickLabelFormatter = stringConverter
logYAxis.tickLabelFormatter = stringConverter
linearYAxis.limitTickLabelsWidth(35.0)
logYAxis.limitTickLabelsWidth(35.0)

linearYAxis.tickUnitProperty() bindTo (colorMapper.maxValueProperty() - colorMapper.minValueProperty()) / colorMapper.numberOfSegmentsProperty()
}

private fun lazyConfigWindowInitOwner() {
Expand All @@ -97,7 +127,7 @@ class ColorAxisController @Inject constructor(
val step = 10.0
val doubleValueFactory = { pref: Preference<Double> ->
SpinnerValueFactory.DoubleSpinnerValueFactory(
0.0,
0.1,
100_000.0,
preferences.getDouble(pref.key, pref.def),
step
Expand Down Expand Up @@ -135,33 +165,41 @@ class ColorAxisController @Inject constructor(
editor.onAction = EventHandler { if (valid.get()) numberOfSegmentsSpinner.commitValue() }
}

initConfig()
}

private fun setupCharts() {
colorMapper.minValueProperty().bind(minValueSpinner.valueProperty())
colorMapper.maxValueProperty().bind(maxValueSpinner.valueProperty())
colorMapper.numberOfSegmentsProperty().bind(numberOfSegmentsSpinner.valueProperty())
isLogChkBox.isSelected = colorMapper.isLogScale
colorMapper.logScaleProperty().bind(isLogChkBox.selectedProperty())

yAxis.lowerBoundProperty().bind(colorMapper.minValueProperty())
yAxis.upperBoundProperty().bind(colorMapper.maxValueProperty())
linearChart.visibleProperty() bindTo !isLogChkBox.selectedProperty()
linearChart.managedProperty() bindTo linearChart.visibleProperty()

initConfig()
logChart.visibleProperty() bindTo !linearChart.visibleProperty()
logChart.managedProperty() bindTo !linearChart.managedProperty()
}

@Suppress("UNCHECKED_CAST")
private fun update() {
val range = colorMapper.maxValue - colorMapper.minValue
chart.data = colorMapper.segments.map {
Series(
observableListOf(
Data(0.0, colorMapper.minValue + it.from * range),
Data(100.0, colorMapper.minValue + it.from * range),
Data(100.0, colorMapper.minValue + it.to * range),
Data(0.0, colorMapper.minValue + it.to * range)
)
) as Series<Number, Number>
// safe upcast Double : Number
}.toObservableList()

chart.data.forEachIndexed { index, series ->
chart.seriesPolygons[series]?.apply { fill = colorMapper.segments[index].color }
with(if (isLogChkBox.isSelected) logChart else linearChart) {
data.setAll(colorMapper.segments.map {
Series(
observableListOf(
Data(0.0, it.from),
Data(100.0, it.from),
Data(100.0, it.to),
Data(0.0, it.to)
)
) as Series<Number, Number>
// safe upcast Double : Number
}.toObservableList())

data.forEachIndexed { index, series ->
seriesPolygons[series]?.apply { fill = colorMapper.segments[index].color }
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ModelSectionController @Inject constructor(
colorMapper.maxValueProperty().addListener { _, _, _ -> update() }
colorMapper.minValueProperty().addListener { _, _, _ -> update() }
colorMapper.numberOfSegmentsProperty().addListener { _, _, _ -> update() }
colorMapper.logScaleProperty().addListener { _, _, _ -> update() }
}

private fun update() {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/ru/nucodelabs/gem/view/color/ColorMapper.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ru.nucodelabs.gem.view.color

import javafx.beans.property.BooleanProperty
import javafx.beans.property.DoubleProperty
import javafx.beans.property.IntegerProperty
import javafx.scene.paint.Color
Expand All @@ -14,5 +15,8 @@ interface ColorMapper {
fun numberOfSegmentsProperty(): IntegerProperty
val segments: List<Segment>

fun logScaleProperty(): BooleanProperty
var isLogScale: Boolean

data class Segment(val from: Double, val to: Double, val color: Color)
}
Loading