Skip to content

Commit

Permalink
added dedicated dataset node parameters class
Browse files Browse the repository at this point in the history
  • Loading branch information
ennerf committed Aug 17, 2023
1 parent ddf444b commit 6f4b30f
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public static class LegendItem extends Label {

public LegendItem(DataSetNode series) {
StyleUtil.addStyles(this, "chart-legend-item");
setText(series.getText());
textProperty().bind(series.textProperty());
setGraphic(symbol);
symbol.widthProperty().bind(symbolWidth);
symbol.heightProperty().bind(symbolHeight);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
import io.fair_acc.dataset.spi.DoubleErrorDataSet;
import io.fair_acc.dataset.utils.NoDuplicatesList;
import io.fair_acc.dataset.utils.ProcessingProfiler;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
Expand All @@ -42,6 +39,7 @@ public abstract class AbstractRenderer<R extends Renderer> extends Parent implem
protected final StyleableBooleanProperty showInLegend = css().createBooleanProperty(this, "showInLegend", true);
protected final StyleableBooleanProperty useGlobalIndex = css().createBooleanProperty(this, "useGlobalIndex", true);
protected final StyleableIntegerProperty indexOffset = css().createIntegerProperty(this, "indexOffset", 0);
protected final IntegerProperty colorCount = css().createIntegerProperty(this, "colorCount", 8);
private final ObservableList<DataSet> datasets = FXCollections.observableArrayList();
private final ObservableList<DataSetNode> dataSetNodes = FXCollections.observableArrayList();
private final ObservableList<Axis> axesList = FXCollections.observableList(new NoDuplicatesList<>());
Expand All @@ -67,13 +65,13 @@ public AbstractRenderer() {
dataSetNodes.setAll(datasets.stream().distinct().map(this::createNode).collect(Collectors.toList()));
});
dataSetNodes.addListener((ListChangeListener<DataSetNode>) c -> updateIndices());
PropUtil.runOnChange(this::updateIndices, useGlobalIndex, indexOffset);
PropUtil.runOnChange(this::updateIndices, useGlobalIndex, indexOffset, colorCount);
}

protected void updateIndices() {
int i = useGlobalIndex.get() ? getIndexOffset() : 0;
for (DataSetNode datasetNode : getDatasetNodes()) {
datasetNode.setColorIndex(i++);
datasetNode.setColorIndex(i++ % getColorCount());
}
}

Expand Down Expand Up @@ -214,6 +212,18 @@ public void setIndexOffset(int indexOffset) {
this.indexOffset.set(indexOffset);
}

public int getColorCount() {
return colorCount.get();
}

public IntegerProperty colorCountProperty() {
return colorCount;
}

public void setColorCount(int colorCount) {
this.colorCount.set(colorCount);
}

/**
* @param prop property that causes the canvas to invalidate
* @return property
Expand Down
Original file line number Diff line number Diff line change
@@ -1,64 +1,67 @@
package io.fair_acc.chartfx.ui.css;

import io.fair_acc.chartfx.marker.DefaultMarker;
import io.fair_acc.chartfx.renderer.spi.AbstractRenderer;
import io.fair_acc.chartfx.utils.PropUtil;
import io.fair_acc.dataset.DataSet;
import io.fair_acc.dataset.event.EventSource;
import io.fair_acc.dataset.events.BitState;
import io.fair_acc.dataset.events.ChartBits;
import io.fair_acc.dataset.events.StateListener;
import io.fair_acc.dataset.utils.AssertUtils;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.css.*;
import javafx.scene.Node;
import javafx.scene.shape.Shape;

import java.util.List;

/**
* A dataset wrapper that lives in the SceneGraph for CSS styling
*
* @author ennerf
*/
public class DataSetNode extends TextStyle implements EventSource {
public class DataSetNode extends DataSetNodeParameter implements EventSource {

public DataSetNode(AbstractRenderer<?> renderer, DataSet dataSet) {
this.renderer = AssertUtils.notNull("renderer", renderer);
this.dataSet = AssertUtils.notNull("dataSet", dataSet);
setVisible(dataSet.isVisible());
setText(dataSet.getName());
PropUtil.runOnChange(() -> dataSet.setVisible(isVisible()), visibleProperty());

// Forward changes from dataset to the node
final StateListener updateText = (src, bits) -> setText(dataSet.getName());
final StateListener updateVisibility = (src, bits) -> setVisible(dataSet.isVisible());
sceneProperty().addListener((observable, oldScene, newScene) -> {
if (oldScene != null) {
dataSet.getBitState().removeInvalidateListener(updateText);
dataSet.getBitState().removeInvalidateListener(updateVisibility);
}
setText(dataSet.getName());
setVisible(dataSet.isVisible());
if (newScene != null) {
dataSet.getBitState().addInvalidateListener(ChartBits.DataSetName, updateText);
dataSet.getBitState().addInvalidateListener(ChartBits.DataSetVisibility, updateVisibility);
}
});

// Initialize with the dataset style TODO: integrate with deprecated style data
if (!PropUtil.isNullOrEmpty(dataSet.getStyle())) {
// TODO: integrate with deprecated style data
setStyle(dataSet.getStyle());
}
var actualColorIndex = Bindings.createIntegerBinding(
() -> colorIndex.get() % maxColors.get(),
colorIndex, maxColors);
actualColorIndex.addListener((observable, oldValue, newValue) -> {

// Forward changes from the node to the dataset TODO: remove visibility from dataset
PropUtil.runOnChange(() -> dataSet.setVisible(isVisible()), visibleProperty());

// Notify style updates via the dataset state. Note that the node could
// have a dedicated state, but that only provides benefits when one
// dataset is in multiple charts where one draw could be skipped.
// TODO: maybe notify the chart directly that the Canvas needs to be redrawn?
changeCounterProperty().addListener(getBitState().onPropChange(ChartBits.DataSetMetaData)::set);

// Integrate with the JavaFX default CSS color selectors
colorIndexProperty().addListener((observable, oldValue, newValue) -> {
if (oldValue != null) {
getStyleClass().removeAll(DefaultColorClasses.getForIndex(oldValue.intValue()));
getStyleClass().removeAll(DefaultColorClass.getForIndex(oldValue.intValue()));
}
if (newValue != null) {
getStyleClass().add(1, DefaultColorClasses.getForIndex(newValue.intValue()));
getStyleClass().add(2, DefaultColorClass.getForIndex(newValue.intValue()));
}
// TODO: reapply CSS? usually set before CSS, but could potentially be modified after CSS too. might be expensive
});
StyleUtil.styleNode(this, "dataset", DefaultColorClasses.getForIndex(actualColorIndex.intValue()));
}

// Index for automatic coloring
final IntegerProperty colorIndex = new SimpleIntegerProperty();
final StyleableIntegerProperty maxColors = css().createIntegerProperty(this, "maxColors", 8);
final StyleableDoubleProperty intensity = css().createDoubleProperty(this, "intensity", 100);
final StyleableBooleanProperty showInLegend = css().createBooleanProperty(this, "showInLegend", true);
final StyleableObjectProperty<DefaultMarker> markerType = css().createEnumProperty(this, "markerType", DefaultMarker.DEFAULT, true, DefaultMarker.class);

@Override
public Node getStyleableNode() {
return this;
StyleUtil.styleNode(this, "dataset", "chart-series-line", DefaultColorClass.getForIndex(getColorIndex()));
}

@Override
Expand All @@ -70,48 +73,15 @@ public DataSet getDataSet() {
return dataSet;
}

public int getColorIndex() {
return colorIndex.get();
}

public IntegerProperty colorIndexProperty() {
return colorIndex;
}

public void setColorIndex(int colorIndex) {
this.colorIndex.set(colorIndex);
}
protected CssPropertyFactory<DataSetNode> css() {
return CSS;
}

@Override
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return css().getCssMetaData();
}

public boolean isShowInLegend() {
return showInLegend.get();
}

public StyleableBooleanProperty showInLegendProperty() {
return showInLegend;
}

public void setShowInLegend(boolean showInLegend) {
this.showInLegend.set(showInLegend);
}

public AbstractRenderer<?> getRenderer() {
return renderer;
}

private final DataSet dataSet;
private final AbstractRenderer<?> renderer;

private static final CssPropertyFactory<DataSetNode> CSS = new CssPropertyFactory<>(Shape.getClassCssMetaData());

static class DefaultColorClasses {
static class DefaultColorClass {

public static String getForIndex(int index) {
if (index >= 0 && index < precomputed.length) {
Expand All @@ -121,7 +91,7 @@ public static String getForIndex(int index) {
}

private static String createDefaultClass(int colorIx) {
return "default-color" + colorIx + ".chart-series-line";
return "default-color" + colorIx;
}

private static final String[] precomputed = new String[20];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package io.fair_acc.chartfx.ui.css;

import io.fair_acc.chartfx.marker.DefaultMarker;
import io.fair_acc.chartfx.utils.PropUtil;
import javafx.beans.property.*;
import javafx.css.*;
import javafx.scene.Node;

import java.util.List;

/**
* Holds the styleable parameters of the DataSetNode
*
* @author ennerf
*/
public abstract class DataSetNodeParameter extends TextStyle {

public DataSetNodeParameter() {
PropUtil.runOnChange(super::incrementChangeCounter,
colorIndex,
intensity,
showInLegend,
markerType
);
}

final IntegerProperty colorIndex = new SimpleIntegerProperty();
final DoubleProperty intensity = css().createDoubleProperty(this, "intensity", 100);
final BooleanProperty showInLegend = css().createBooleanProperty(this, "showInLegend", true);
final ObjectProperty<DefaultMarker> markerType = css().createEnumProperty(this, "markerType", DefaultMarker.DEFAULT, true, DefaultMarker.class);

public int getColorIndex() {
return colorIndex.get();
}

public IntegerProperty colorIndexProperty() {
return colorIndex;
}

public void setColorIndex(int colorIndex) {
this.colorIndex.set(colorIndex);
}

public double getIntensity() {
return intensity.get();
}

public DoubleProperty intensityProperty() {
return intensity;
}

public void setIntensity(double intensity) {
this.intensity.set(intensity);
}

public boolean isShowInLegend() {
return showInLegend.get();
}

public BooleanProperty showInLegendProperty() {
return showInLegend;
}

public void setShowInLegend(boolean showInLegend) {
this.showInLegend.set(showInLegend);
}

public DefaultMarker getMarkerType() {
return markerType.get();
}

public ObjectProperty<DefaultMarker> markerTypeProperty() {
return markerType;
}

public void setMarkerType(DefaultMarker markerType) {
this.markerType.set(markerType);
}

@Override
public Node getStyleableNode() {
return this;
}

protected CssPropertyFactory<DataSetNodeParameter> css() {
return CSS;
}

@Override
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return css().getCssMetaData();
}

private static final CssPropertyFactory<DataSetNodeParameter> CSS = new CssPropertyFactory<>(TextStyle.getClassCssMetaData());

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public TextStyle(String... styles) {
StyleUtil.forEachStyleProp(this, StyleUtil.incrementOnChange(changeCounter));
}

protected void incrementChangeCounter() {
changeCounter.set(changeCounter.get() + 1);
}

@Override
public String toString() {
return StyleUtil.toStyleString(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
.chart .renderer {
-fx-show-in-legend: true;
-fx-use-global-index: true;
-fx-color-count: 8;
-fx-assume-sorted-data: true;
-fx-min-required-reduction-size: 5;
-fx-parallel-implementation: true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ $null: null; // null gets removed from Sass. Maybe create a placeholder and repl
// abstract renderer
-fx-show-in-legend: true;
-fx-use-global-index: true;
-fx-color-count: 8;

// point reducing renderers
-fx-assume-sorted-data: true;
Expand Down

0 comments on commit 6f4b30f

Please sign in to comment.