-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
991 additions
and
19 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
fireplace-app/src/main/kotlin/io/github/bric3/fireplace/charts/CharUtils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Fireplace | ||
* | ||
* Copyright (c) 2021, Today - Brice Dutheil | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
*/ | ||
package io.github.bric3.fireplace.charts | ||
|
||
import java.awt.Color | ||
|
||
|
||
fun Color.withAlpha(alpha: Float) = Color( | ||
red, | ||
green, | ||
blue, | ||
(alpha * 255).toInt() | ||
) |
140 changes: 140 additions & 0 deletions
140
fireplace-app/src/main/kotlin/io/github/bric3/fireplace/charts/Chart.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/* | ||
* Fireplace | ||
* | ||
* Copyright (c) 2021, Today - Brice Dutheil | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
*/ | ||
package io.github.bric3.fireplace.charts | ||
|
||
import io.github.bric3.fireplace.charts.ChartSpecification.LineRendererDescriptor | ||
import io.github.bric3.fireplace.charts.ChartSpecification.RendererDescriptor | ||
import java.awt.Color | ||
import java.awt.Graphics2D | ||
import java.awt.RenderingHints | ||
import java.awt.geom.Rectangle2D | ||
import java.beans.PropertyChangeListener | ||
import java.beans.PropertyChangeSupport | ||
|
||
/** | ||
* A chart that can be inlaid into a small space. Generally a chart will render a single dataset, but it is | ||
* also possible to overlay multiple renderer/dataset pairs in the same space. | ||
*/ | ||
class Chart : RectangleContent { | ||
private val propertyChangeSupport = PropertyChangeSupport(this) | ||
|
||
/** | ||
* A list of cart specifications. | ||
* | ||
* @see ChartSpecification | ||
*/ | ||
var chartSpecifications: List<ChartSpecification> = emptyList() | ||
set(value) { | ||
val oldChartDatasetDescriptor = field | ||
if (oldChartDatasetDescriptor == value) { | ||
return | ||
} | ||
|
||
field = value | ||
propertyChangeSupport.firePropertyChange("charDatasetDescriptors", oldChartDatasetDescriptor, value) | ||
} | ||
|
||
/** | ||
* A background painter for the chart, possibly `null`. | ||
*/ | ||
var background: RectangleContent? = null | ||
set(value) { | ||
val oldBackground = field | ||
if (oldBackground == value) { | ||
return | ||
} | ||
field = value | ||
propertyChangeSupport.firePropertyChange("background", oldBackground, value) | ||
} | ||
|
||
/** | ||
* The insets (applied after the background has been drawn). | ||
*/ | ||
var insets: RectangleMargin = RectangleMargin(2.0, 2.0, 2.0, 2.0) | ||
set(value) { | ||
val oldInsets = field | ||
if (oldInsets == field) { | ||
return | ||
} | ||
field = value | ||
propertyChangeSupport.firePropertyChange("insets", oldInsets, value) | ||
} | ||
|
||
/** | ||
* The insets for the plot area (defaults to zero but can be modified to add space for | ||
* annotations etc). | ||
*/ | ||
var plotInsets: RectangleMargin = RectangleMargin(0.0, 0.0, 0.0, 0.0) | ||
set(value) { | ||
val oldPlotInsets = field | ||
if (oldPlotInsets == value) { | ||
return | ||
} | ||
|
||
field = value | ||
propertyChangeSupport.firePropertyChange("plotInsets", oldPlotInsets, value) | ||
} | ||
|
||
/** | ||
* Creates a new chart with the given specifications, dataset and renderer. | ||
* | ||
* @param chartSpecifications The chart specifications | ||
*/ | ||
constructor(chartSpecifications: List<ChartSpecification>) { | ||
// TODO how to ensure consistent ranges across multiple charts? | ||
this.chartSpecifications = chartSpecifications | ||
} | ||
|
||
fun addPropertyChangeListener(listener: PropertyChangeListener?) { | ||
propertyChangeSupport.addPropertyChangeListener(listener) | ||
} | ||
|
||
fun removePropertyChangeListener(listener: PropertyChangeListener?) { | ||
propertyChangeSupport.removePropertyChangeListener(listener) | ||
} | ||
|
||
/** | ||
* Draws the chart to a Java2D graphics target. | ||
* | ||
* @param g2 the graphics target (`null` not permitted). | ||
* @param bounds the bounds within which the chart should be drawn. | ||
*/ | ||
override fun draw(g2: Graphics2D, bounds: Rectangle2D) { | ||
// set up any rendering hints we want (should allow this to be controlled externally) | ||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) | ||
|
||
if (background != null) { | ||
background!!.draw(g2, bounds) | ||
} | ||
|
||
// handle background, margin, border, insets and fill | ||
insets.applyInsets(bounds) | ||
|
||
val plotArea = plotInsets.shrink(bounds) | ||
|
||
chartSpecifications.forEach { | ||
// plot its dataset in the inner bounds | ||
configureRenderer(it.renderer).draw(this, it.dataset, g2, plotArea) | ||
} | ||
} | ||
|
||
private val lineChartRenderer = LineChartRenderer() | ||
|
||
private fun configureRenderer(rendererSpec: RendererDescriptor): ChartRenderer { | ||
return when (rendererSpec) { | ||
is LineRendererDescriptor -> lineChartRenderer.apply { | ||
linePaint = rendererSpec.lineColor ?: Color.BLACK | ||
fillColors = rendererSpec.fillColors | ||
} | ||
|
||
else -> error("Unsupported render spec") | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
fireplace-app/src/main/kotlin/io/github/bric3/fireplace/charts/ChartComponent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Fireplace | ||
* | ||
* Copyright (c) 2021, Today - Brice Dutheil | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
*/ | ||
package io.github.bric3.fireplace.charts | ||
|
||
import java.awt.Graphics | ||
import java.awt.Graphics2D | ||
import java.awt.Rectangle | ||
import java.beans.PropertyChangeSupport | ||
import javax.swing.* | ||
|
||
/** | ||
* A component that draws an [Chart] within the bounds of the component. | ||
* | ||
* @param chart the chart. | ||
*/ | ||
class ChartComponent(chart: Chart? = null) : JComponent() { | ||
private val propertyChangeSupport = PropertyChangeSupport(this) | ||
|
||
var chart: Chart? = chart | ||
set(value) { | ||
val oldChart = field | ||
if (oldChart == value) { | ||
return | ||
} | ||
field = value | ||
propertyChangeSupport.firePropertyChange("chart", oldChart, value) | ||
} | ||
|
||
/** A reusable rectangle to avoid creating work for the garbage collector. */ | ||
private val rect = Rectangle() | ||
|
||
init { | ||
border = null | ||
propertyChangeSupport.addPropertyChangeListener("chart") { | ||
revalidate() | ||
repaint() | ||
} | ||
} | ||
|
||
/** | ||
* Paints the component. The chart will be drawn at a size matching the | ||
* bounds of the component. | ||
* | ||
* @param g the Java2D graphics target. | ||
*/ | ||
override fun paintComponent(g: Graphics) { | ||
super.paintComponent(g) | ||
chart?.let { | ||
val g2 = g as Graphics2D | ||
getBounds(rect) | ||
g.translate(-rect.x, -rect.y) | ||
it.draw(g2, rect) | ||
g.translate(rect.x, rect.y) | ||
} | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
fireplace-app/src/main/kotlin/io/github/bric3/fireplace/charts/ChartRenderer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Fireplace | ||
* | ||
* Copyright (c) 2021, Today - Brice Dutheil | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
*/ | ||
package io.github.bric3.fireplace.charts | ||
|
||
import java.awt.Graphics2D | ||
import java.awt.geom.Rectangle2D | ||
|
||
/** | ||
* A renderer for an [Chart] that draws data with a particular representation | ||
* (for example, lines or bars). | ||
* | ||
* @param background the background (`null` permitted). | ||
*/ | ||
abstract class ChartRenderer @JvmOverloads constructor(private val background: RectangleContent? = null) { | ||
/** | ||
* Draws a representation of the supplied dataset within the plot bounds of the supplied | ||
* Java2D graphics target. The chart can be used to provide some global attributes for the | ||
* rendering (such as the x-range and y-range for display). | ||
* | ||
* @param chart the chart. | ||
* @param dataset the dataset. | ||
* @param g2 the Java2D graphics target. | ||
* @param plotBounds the plot bounds. | ||
*/ | ||
open fun draw(chart: Chart, dataset: XYDataset, g2: Graphics2D, plotBounds: Rectangle2D) { | ||
if (this.background != null) { | ||
background.draw(g2, plotBounds) | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
fireplace-app/src/main/kotlin/io/github/bric3/fireplace/charts/ChartSpecification.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Fireplace | ||
* | ||
* Copyright (c) 2021, Today - Brice Dutheil | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
*/ | ||
package io.github.bric3.fireplace.charts | ||
|
||
import java.awt.Color | ||
|
||
/** | ||
* Specifies the various properties of a chart (dataset, label, how it's rendered). | ||
*/ | ||
data class ChartSpecification( | ||
val dataset: XYDataset, | ||
val label: String, | ||
val renderer: RendererDescriptor, | ||
) { | ||
/** | ||
* Common interface for specifying how chart is rendered. | ||
*/ | ||
sealed interface RendererDescriptor | ||
|
||
/** | ||
* Specifies a **line-rendered** chart. | ||
*/ | ||
data class LineRendererDescriptor( | ||
val lineColor: Color? = null, | ||
val fillColors: List<Color>? = null, | ||
) : RendererDescriptor | ||
} |
Oops, something went wrong.