Skip to content

Commit 8c384db

Browse files
committed
support different symbol types and colors of series
1 parent 6d4c9b6 commit 8c384db

File tree

5 files changed

+1895
-102
lines changed

5 files changed

+1895
-102
lines changed

.classpath

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<classpath>
3+
<classpathentry kind="con" path="org.eclipse.fx.ide.jdt.core.JAVAFX_CONTAINER">
4+
<attributes>
5+
<attribute name="module" value="true"/>
6+
</attributes>
7+
</classpathentry>
38
<classpathentry kind="src" output="target/classes" path="src/main/java">
49
<attributes>
510
<attribute name="optional" value="true"/>
611
<attribute name="maven.pomderived" value="true"/>
712
</attributes>
813
</classpathentry>
9-
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-10">
14+
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
1015
<attributes>
1116
<attribute name="maven.pomderived" value="true"/>
1217
</attributes>
1318
</classpathentry>
14-
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
19+
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
1520
<attributes>
21+
<attribute name="test" value="true"/>
22+
<attribute name="optional" value="true"/>
1623
<attribute name="maven.pomderived" value="true"/>
1724
</attributes>
1825
</classpathentry>
19-
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
26+
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
2027
<attributes>
28+
<attribute name="test" value="true"/>
2129
<attribute name="maven.pomderived" value="true"/>
2230
</attributes>
2331
</classpathentry>
24-
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
32+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-10">
2533
<attributes>
26-
<attribute name="optional" value="true"/>
34+
<attribute name="module" value="true"/>
2735
<attribute name="maven.pomderived" value="true"/>
28-
<attribute name="test" value="true"/>
2936
</attributes>
3037
</classpathentry>
31-
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
38+
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
3239
<attributes>
3340
<attribute name="maven.pomderived" value="true"/>
34-
<attribute name="test" value="true"/>
3541
</attributes>
3642
</classpathentry>
3743
<classpathentry kind="output" path="target/classes"/>

src/main/java/com/github/kilianB/MultiTypeChart.java

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,16 @@
3636
import javafx.scene.Group;
3737
import javafx.scene.Node;
3838
import javafx.scene.chart.Axis;
39+
import javafx.scene.chart.LineChart.SortingPolicy;
40+
import javafx.scene.chart.NumberAxis;
3941
import javafx.scene.chart.XYChart;
4042
import javafx.scene.control.Label;
4143
import javafx.scene.effect.ColorAdjust;
4244
import javafx.scene.input.MouseEvent;
43-
import javafx.scene.chart.LineChart.SortingPolicy;
44-
import javafx.scene.chart.NumberAxis;
4545
import javafx.scene.layout.Background;
4646
import javafx.scene.layout.BackgroundFill;
4747
import javafx.scene.layout.CornerRadii;
4848
import javafx.scene.layout.StackPane;
49-
import javafx.scene.paint.Color;
5049
import javafx.scene.shape.ClosePath;
5150
import javafx.scene.shape.LineTo;
5251
import javafx.scene.shape.MoveTo;
@@ -76,7 +75,7 @@ public enum SeriesType {
7675

7776
// Global chart properties
7877
private static final String COLOR_CSS_CLASS = "default-color";
79-
private static final String LINE_CHART_LINE_CSS_CLASS = "chart-series-line";
78+
private static final String LINE_CHART_LINE_CSS_CLASS = "series-line";
8079
private static final String LINE_CHART_SYMBOL_CSS_CLASS = "chart-line-symbol";
8180
private static final String SCATTER_CHART_SYMBOL_CSS_CLASS = "chart-symbol";
8281

@@ -93,17 +92,18 @@ public enum SeriesType {
9392

9493
protected HashMap<Series<X, Y>, TypedSeries<X, Y>> typedSeries = new LinkedHashMap<>();
9594
protected HashMap<Series<X, Y>, Boolean> seriesVisibility = new HashMap<>();
95+
protected HashMap<Series<X, Y>, SymbolType> seriesSymbolType = new HashMap<>();
9696

9797
/** A package private hashmap in the chart object */
9898
protected Map<Series<X, Y>, Integer> seriesColorMap = new HashMap<>();
9999
protected BitSet availableColors = new BitSet(8);
100100

101-
//TODO
101+
// TODO
102102
// private static final Color[] availableColorsExtended = new Color[164];
103103
// static {
104104
//
105105
// }
106-
106+
107107
// Area chart
108108
/** Remember the current animation state of area charts for layout */
109109
private Map<Series<X, Y>, DoubleProperty> seriesYMultiplierMap = new HashMap<>();
@@ -201,9 +201,6 @@ protected Insets computeValue() {
201201
for (var entry : additionalXAxis.entrySet()) {
202202
double height = entry.getValue().getHeight();
203203

204-
System.out.println("X Axis: " + height + " " + entry.getValue() + " " + entry.getValue().getWidth()
205-
+ entry.getValue().getSide());
206-
207204
switch (entry.getValue().getSide()) {
208205
case TOP:
209206
top += (height + AXIS_PADDING);
@@ -215,11 +212,8 @@ protected Insets computeValue() {
215212
throw new IllegalStateException("X Axis may only be positioned top or bottom");
216213
}
217214
}
218-
System.out.println(top + " " + right + " " + bottom + " " + left);
219215
return new Insets(top, right, bottom, left);
220-
221216
}
222-
223217
};
224218

225219
this.paddingProperty().bind(paddingBinding);
@@ -274,6 +268,9 @@ public boolean addSeries(TypedSeries<X, Y> series) throws IllegalArgumentExcepti
274268

275269
// we need to change the series
276270
Series<X, Y> ser = series.getSeries();
271+
SymbolType t = seriesSymbolType.get(series);
272+
String symTypeCss = (t != null)? t.name() : "";
273+
277274
for (int itemIndex = 0; itemIndex < ser.getData().size(); itemIndex++) {
278275
Data<X, Y> item = ser.getData().get(itemIndex);
279276
Node symbol = item.getNode();
@@ -288,7 +285,7 @@ public boolean addSeries(TypedSeries<X, Y> series) throws IllegalArgumentExcepti
288285
identifier = AREA_CHART_SYMBOL_CSS_CLASS;
289286
break;
290287
}
291-
this.createSymbols(ser, itemIndex, item, identifier);
288+
this.createSymbols(ser, itemIndex, item, identifier,symTypeCss);
292289

293290
symbol = item.getNode();
294291
getPlotChildren().add(symbol);
@@ -489,37 +486,47 @@ protected void seriesChanged(ListChangeListener.Change<? extends Series> c) {
489486

490487
String seriesColor = COLOR_CSS_CLASS + seriesColorMap.get(s);
491488

489+
SymbolType symType = seriesSymbolType.get(s);
490+
String symTypeCss = (symType != null) ? symType.name():"";
491+
492+
492493
switch (type.getSeriesType()) {
493494
case AREA:
494495
Path seriesLine = (Path) ((Group) s.getNode()).getChildren().get(1);
495496
Path fillPath = (Path) ((Group) s.getNode()).getChildren().get(0);
496497
seriesLine.getStyleClass().setAll(AREA_CHART_SERIES_LINE_CSS_CLASS, "series" + i, seriesColor);
497498
fillPath.getStyleClass().setAll(AREA_CHART_FILL_CSS_CLASS, "series" + i, seriesColor);
499+
500+
498501
for (int j = 0; j < s.getData().size(); j++) {
499502
final Data<X, Y> item = s.getData().get(j);
500503
final Node node = item.getNode();
501504
if (node != null)
502-
node.getStyleClass().setAll(AREA_CHART_SYMBOL_CSS_CLASS, "series" + i, "data" + j, seriesColor);
505+
node.getStyleClass().setAll(AREA_CHART_SYMBOL_CSS_CLASS, "series" + i, "data" + j, seriesColor,symTypeCss);
503506
}
504507
break;
505508
case LINE:
506509
Node seriesNode = s.getNode();
507510
if (seriesNode != null)
508511
seriesNode.getStyleClass().setAll(LINE_CHART_LINE_CSS_CLASS, "series" + i, seriesColor);
512+
509513
for (int j = 0; j < s.getData().size(); j++) {
510514
final Node symbol = s.getData().get(j).getNode();
511515
if (symbol != null)
512516
symbol.getStyleClass().setAll(LINE_CHART_SYMBOL_CSS_CLASS, "series" + i, "data" + j,
513-
seriesColor);
517+
seriesColor,symTypeCss);
514518
}
515519
break;
516520

517521
case SCATTER:
522+
518523
for (int j = 0; j < s.getData().size(); j++) {
519524
final Node symbol = s.getData().get(j).getNode();
520-
if (symbol != null)
525+
if (symbol != null) {
521526
symbol.getStyleClass().setAll(SCATTER_CHART_SYMBOL_CSS_CLASS, "series" + i, "data" + j,
522-
seriesColor);
527+
seriesColor,symTypeCss);
528+
}
529+
523530
}
524531
break;
525532
case STACKED_AREA:
@@ -831,13 +838,20 @@ protected void layoutScatterSeries(Series<X, Y> series, Axis<X> xAxis, Axis<Y> y
831838
// Add data item
832839
protected void addAreaItem(Series<X, Y> series, int itemIndex, Data<X, Y> item) {
833840
// TODO add animation code
834-
createSymbols(series, itemIndex, item, AREA_CHART_SYMBOL_CSS_CLASS);
841+
842+
SymbolType t = seriesSymbolType.get(series);
843+
String symTypeCss = (t != null)? t.name() : "";
844+
845+
createSymbols(series, itemIndex, item, AREA_CHART_SYMBOL_CSS_CLASS,symTypeCss);
835846
getPlotChildren().add(item.getNode());
836847
}
837848

838849
protected void addScatterItem(Series<X, Y> series, int itemIndex, Data<X, Y> item) {
839850

840-
createSymbols(series, itemIndex, item, SCATTER_CHART_SYMBOL_CSS_CLASS);
851+
SymbolType t = seriesSymbolType.get(series);
852+
String symTypeCss = (t != null)? t.name() : "";
853+
854+
createSymbols(series, itemIndex, item, SCATTER_CHART_SYMBOL_CSS_CLASS,symTypeCss);
841855
Node symbol = item.getNode();
842856

843857
// add and fade in new symbol if animated
@@ -854,9 +868,12 @@ protected void addScatterItem(Series<X, Y> series, int itemIndex, Data<X, Y> ite
854868

855869
protected void addLineItem(Series<X, Y> series, int itemIndex, Data<X, Y> item) {
856870

871+
SymbolType t = seriesSymbolType.get(series);
872+
String symTypeCss = (t != null)? t.name() : "";
873+
857874
// Create the node
858875
if (typedSeries.get(series).showSymbolsProperty().get()) {
859-
createSymbols(series, itemIndex, item, LINE_CHART_SYMBOL_CSS_CLASS);
876+
createSymbols(series, itemIndex, item, LINE_CHART_SYMBOL_CSS_CLASS,symTypeCss);
860877
}
861878
Node symbol = item.getNode();
862879

@@ -867,7 +884,7 @@ protected void addLineItem(Series<X, Y> series, int itemIndex, Data<X, Y> item)
867884
// TODO add animation code
868885
}
869886

870-
private void createSymbols(Series<X, Y> series, int itemIndex, Data<X, Y> item, String symbolCSSIdentifier) {
887+
private void createSymbols(Series<X, Y> series, int itemIndex, Data<X, Y> item, String symbolCSSIdentifier,String additionalCss) {
871888
Node symbol = item.getNode();
872889
// TODO should we also check here is e.g. scatter chart ticks should be drawn?
873890
if (symbol == null) {
@@ -880,7 +897,7 @@ private void createSymbols(Series<X, Y> series, int itemIndex, Data<X, Y> item,
880897

881898
if (symbol != null) {
882899
symbol.getStyleClass().addAll(symbolCSSIdentifier, "series" + getData().indexOf(series), "data" + itemIndex,
883-
COLOR_CSS_CLASS + seriesColorMap.get(series));
900+
COLOR_CSS_CLASS + seriesColorMap.get(series),additionalCss);
884901
}
885902
}
886903

@@ -1116,7 +1133,6 @@ public void setSeriesVisibility(TypedSeries series, boolean b) {
11161133

11171134
protected void toggleSeriesVisability(Series<X, Y> series, boolean b) {
11181135
seriesVisibility.put(series, b);
1119-
System.out.println("Toogle Series");
11201136
this.requestChartLayout();
11211137
}
11221138

@@ -1141,9 +1157,12 @@ protected void updateLegend() {
11411157
name = "Series " + seriesIndex;
11421158
}
11431159

1160+
SymbolType t = seriesSymbolType.get(series);
1161+
String symTypeCss = (t != null)? t.name() : "";
1162+
11441163
Node symbol = new StackPane();
11451164
symbol.getStyleClass().addAll("chart-legend-symbol", "default-color" + seriesColorMap.get(series),
1146-
"chart-symbol"); // This css class contains background-color of the chart. Just go ahead and use
1165+
"chart-symbol",symTypeCss); // This css class contains background-color of the chart. Just go ahead and use
11471166
// it
11481167
LegendItem lItem = new LegendItem(name, symbol);
11491168

@@ -1259,11 +1278,66 @@ public void removeValueMarker(ValueMarker<?> markerToRemove) {
12591278

12601279
markerLock.unlock();
12611280
}
1262-
12631281

1282+
/*
1283+
* Series can be used in multiple chart. How styling is performed is bound to a
1284+
* chart object, therefore use these functions to set the display type
1285+
*/
12641286

1265-
1266-
1267-
1287+
/**
1288+
* Set the series to the specified color. The colors can be found in the
1289+
* chart.css file.
1290+
*
1291+
* @param seriesIndex the index of the series
1292+
* @param colorIndex in range of [0-168]
1293+
*/
1294+
public void setSeriesColor(int seriesIndex, int colorIndex) {
1295+
// Gettings the index in a linked hashset is expensive. This won't be performed
1296+
// many times!
1297+
int index = 0;
1298+
for (var entry : typedSeries.entrySet()) {
1299+
if (index++ == seriesIndex) {
1300+
setSeriesColor(entry.getKey(), colorIndex);
1301+
break;
1302+
}
1303+
}
1304+
}
1305+
1306+
/**
1307+
* Set the series to the specified color. The colors can be found in the
1308+
* chart.css file.
1309+
*
1310+
* @param series the series to set the color for
1311+
* @param colorIndex in range of [0-146]
1312+
*/
1313+
public void setSeriesColor(Series series, int colorIndex) {
1314+
if (series != null) {
1315+
seriesColorMap.put(series, colorIndex);
1316+
legendMap.get(series);
1317+
updateLegend();
1318+
this.seriesChanged(null);
1319+
}
1320+
}
1321+
1322+
public void setSeriesSymbol(int seriesIndex, SymbolType type) {
1323+
// Gettings the index in a linked hashset is expensive. This won't be performed
1324+
// many times!
1325+
int index = 0;
1326+
for (var entry : typedSeries.entrySet()) {
1327+
if (index++ == seriesIndex) {
1328+
setSeriesSymbol(entry.getKey(), type);
1329+
break;
1330+
}
1331+
}
1332+
}
1333+
1334+
public void setSeriesSymbol(Series series, SymbolType type) {
1335+
if (series != null) {
1336+
seriesSymbolType.put(series,type);
1337+
legendMap.get(series);
1338+
updateLegend();
1339+
this.seriesChanged(null);
1340+
}
1341+
}
12681342

12691343
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.github.kilianB;
2+
3+
/**
4+
* Symbol types for legend and chart
5+
* @author Kilian
6+
*
7+
*/
8+
public enum SymbolType {
9+
10+
solidSquare,
11+
solidDiamond,
12+
solidCross,
13+
solidTriangle,
14+
solidCicrle,
15+
16+
//Hollow not yet implemented
17+
hollowSquare,
18+
hollowDiamond,
19+
hollowCross,
20+
hollowTriangle,
21+
hollowCircle;
22+
}

0 commit comments

Comments
 (0)