Skip to content

Commit d8c91f0

Browse files
committed
Add zooming to SmartChartDouble
1 parent 063686e commit d8c91f0

File tree

7 files changed

+521
-347
lines changed

7 files changed

+521
-347
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ There are two versions, SmartChart and SmartChartDouble. The only difference bet
88
- Graph can be reset
99
- Graph can export data to a csv file in the location USER\_HOME\_DIRECTORY/SmartDashboard/VARIABLE\_NAME.csv
1010
- Graph can show multiple data sets simultaneously, by sending SmartDashboard a string with the format "[num1]:[num2]:[num3]:...". Eg. "1.0:2.3:5.6"
11-
- If not showing multiple data sets simultaneously, can zoom in on graph by clicking and dragging on the graph.
11+
- Can zoom in on graph by clicking and dragging on the graph.
1212

1313
##Planned features:
14-
- Zooming while showing multiple data sets
1514
- Scrolling
1615

1716
##Installation
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package edu.nr;
2+
3+
import javafx.beans.property.BooleanProperty;
4+
import javafx.beans.property.ObjectProperty;
5+
import javafx.beans.property.SimpleBooleanProperty;
6+
import javafx.beans.property.SimpleObjectProperty;
7+
import javafx.event.EventHandler;
8+
import javafx.geometry.Point2D;
9+
import javafx.scene.chart.LineChart;
10+
import javafx.scene.chart.NumberAxis;
11+
import javafx.scene.input.MouseEvent;
12+
import javafx.scene.shape.Rectangle;
13+
14+
/**
15+
* Created by garrison on 24-1-17.
16+
*/
17+
public abstract class GenericNRChart<T> extends LineChart<Number, Number> {
18+
19+
public long startTimeMillis;
20+
21+
public BooleanProperty isAutoZooming;
22+
23+
GenericSmartChart chart;
24+
25+
26+
public GenericNRChart(GenericSmartChart chart) {
27+
super(new NumberAxis(), new NumberAxis());
28+
setAnimated(false);
29+
30+
isAutoZooming = new SimpleBooleanProperty();
31+
setAutoZooming(true);
32+
33+
((NumberAxis)getXAxis()).setForceZeroInRange(false);
34+
((NumberAxis)getYAxis()).setForceZeroInRange(false);
35+
36+
setLegendVisible(false);
37+
38+
this.chart = chart;
39+
40+
41+
42+
}
43+
44+
public void setAutoZooming(boolean val) {
45+
getXAxis().setAutoRanging(val);
46+
getYAxis().setAutoRanging(val);
47+
48+
isAutoZooming.set(val);
49+
}
50+
51+
public boolean isAutoZooming() {
52+
return isAutoZooming.get();
53+
}
54+
55+
public abstract void save();
56+
57+
public abstract void reset();
58+
59+
protected void setUpZooming(final Rectangle rect) {
60+
final ObjectProperty<Point2D> mouseAnchor = new SimpleObjectProperty<>();
61+
this.setOnMousePressed(new EventHandler<MouseEvent>() {
62+
@Override
63+
public void handle(MouseEvent event) {
64+
mouseAnchor.set(new Point2D(event.getX(), event.getY()));
65+
rect.setWidth(0);
66+
rect.setHeight(0);
67+
}
68+
});
69+
this.setOnMouseDragged(new EventHandler<MouseEvent>() {
70+
@Override
71+
public void handle(MouseEvent event) {
72+
double x = event.getX();
73+
double y = event.getY();
74+
rect.setX(Math.min(x, mouseAnchor.get().getX()));
75+
rect.setY(Math.min(y, mouseAnchor.get().getY()));
76+
rect.setWidth(Math.abs(x - mouseAnchor.get().getX()));
77+
rect.setHeight(Math.abs(y - mouseAnchor.get().getY()));
78+
}
79+
});
80+
}
81+
82+
public void doZoom(Rectangle zoomRect) {
83+
final NumberAxis yAxis = (NumberAxis) getYAxis();
84+
final NumberAxis xAxis = (NumberAxis) getXAxis();
85+
//Point2D yAxisInScene = yAxis.localToScene(0, 0);
86+
//Point2D xAxisInScene = xAxis.localToScene(0, 0);
87+
double xtopLeftCornerOfGraph = 52;
88+
double ytopLeftCornerOfGraph = 17;
89+
90+
double x = zoomRect.getX() - xtopLeftCornerOfGraph;
91+
double y = zoomRect.getY() - ytopLeftCornerOfGraph;
92+
double w = zoomRect.getWidth();
93+
double h = zoomRect.getHeight();
94+
95+
double width_pixels = this.getWidth() - 65; //65 is the number of pixels of padding
96+
double height_pixels = this.getHeight() - 65;
97+
98+
double width_value = xAxis.getUpperBound() - xAxis.getLowerBound();
99+
double height_value = yAxis.getUpperBound() - yAxis.getLowerBound();
100+
101+
//Point2D zoomTopLeft = new Point2D(zoomRect.getX(), zoomRect.getY());
102+
//Point2D zoomBottomRight = new Point2D(zoomRect.getX() + zoomRect.getWidth(), zoomRect.getY() + zoomRect.getHeight());
103+
//double xOffset = zoomTopLeft.getX() - yAxisInScene.getX();
104+
//double yOffset = zoomBottomRight.getY() - xAxisInScene.getY();
105+
double xAxisScale = width_pixels/width_value;
106+
double yAxisScale = height_pixels/height_value;
107+
108+
double xLower = xAxis.getLowerBound();
109+
double yUpper = yAxis.getUpperBound();
110+
111+
xAxis.setLowerBound(xLower + x / xAxisScale);
112+
xAxis.setUpperBound(xLower + (x+w)/ xAxisScale);
113+
yAxis.setUpperBound(yUpper - y / yAxisScale);
114+
yAxis.setLowerBound(yUpper - (y+h) / yAxisScale);
115+
zoomRect.setWidth(0);
116+
zoomRect.setHeight(0);
117+
}
118+
119+
public abstract double getLowestX();
120+
121+
public abstract double getLowestY();
122+
123+
public abstract double getHighestX();
124+
125+
public abstract double getHighestY();
126+
127+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package edu.nr;
2+
3+
import dashfx.lib.controls.Control;
4+
import dashfx.lib.controls.Designable;
5+
import dashfx.lib.data.DataCoreProvider;
6+
import javafx.beans.binding.BooleanBinding;
7+
import javafx.beans.property.SimpleStringProperty;
8+
import javafx.beans.property.StringProperty;
9+
import javafx.beans.value.ChangeListener;
10+
import javafx.beans.value.ObservableValue;
11+
import javafx.event.ActionEvent;
12+
import javafx.event.EventHandler;
13+
import javafx.geometry.Pos;
14+
import javafx.scene.Node;
15+
import javafx.scene.chart.NumberAxis;
16+
import javafx.scene.control.Button;
17+
import javafx.scene.layout.GridPane;
18+
import javafx.scene.paint.Color;
19+
import javafx.scene.shape.Rectangle;
20+
21+
/**
22+
* Created by garrison on 24-1-17.
23+
*/
24+
public abstract class GenericSmartChart extends GridPane
25+
implements Control, ChangeListener<Object> {
26+
27+
StringProperty name = new SimpleStringProperty();
28+
29+
@Designable(value="Name", description="The name the control binds to")
30+
public final StringProperty nameProperty()
31+
{
32+
return this.name;
33+
}
34+
35+
public final String getName()
36+
{
37+
return this.name.getValue();
38+
}
39+
40+
public final void setName(String value)
41+
{
42+
this.name.setValue(value);
43+
}
44+
45+
46+
public GenericSmartChart () {
47+
48+
setAlignment(Pos.CENTER);
49+
50+
51+
}
52+
53+
54+
public final void registered(final DataCoreProvider provider)
55+
{
56+
if (getName() != null) {
57+
provider.getObservable(getName()).addListener(this);
58+
}
59+
this.name.addListener(new ChangeListener<String>() {
60+
public void changed(ObservableValue<? extends String> ov, String t, String t1) {
61+
if (t != null) {
62+
provider.getObservable(t).removeListener(GenericSmartChart.this);
63+
}
64+
provider.getObservable(t1).addListener(GenericSmartChart.this);
65+
}
66+
});
67+
}
68+
69+
public final Node getUi()
70+
{
71+
return this;
72+
}
73+
74+
public abstract void changed(ObservableValue<? extends Object> ov, Object old, Object t1);
75+
76+
}

SmartChart/src/edu/nr/NRChart.java

Lines changed: 9 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,19 @@
2424
/**
2525
* Created by Nashoba1768 on 1/22/2017.
2626
*/
27-
class NRChart extends LineChart<Number, Number>
27+
class NRChart extends GenericNRChart
2828
{
2929
private Series series = new Series();
30-
private long startTimeMillis;
3130

32-
SmartChart chart;
3331

34-
public BooleanProperty isAutoZooming;
3532

3633
public NRChart(SmartChart chart)
3734
{
38-
super(new NumberAxis(), new NumberAxis());
39-
setAnimated(false);
40-
41-
isAutoZooming = new SimpleBooleanProperty();
42-
setAutoZooming(true);
43-
44-
((NumberAxis)getXAxis()).setForceZeroInRange(false);
45-
((NumberAxis)getYAxis()).setForceZeroInRange(false);
46-
setLegendVisible(false);
35+
super(chart);
4736
getData().add(this.series);
48-
this.chart = chart;
4937
}
5038

51-
public void addValue(double x)
39+
public void addValue(Double x)
5240
{
5341
if(this.series.getData().size() == 0)
5442
{
@@ -64,11 +52,13 @@ public void addValue(double x)
6452
}
6553
}
6654

55+
@Override
6756
public void reset()
6857
{
6958
this.series.getData().clear();
7059
}
7160

61+
@Override
7262
public void save()
7363
{
7464
StringBuilder sb = new StringBuilder();
@@ -101,66 +91,7 @@ public void save()
10191
}
10292
}
10393

104-
protected void setUpZooming(final Rectangle rect) {
105-
final ObjectProperty<Point2D> mouseAnchor = new SimpleObjectProperty<>();
106-
this.setOnMousePressed(new EventHandler<MouseEvent>() {
107-
@Override
108-
public void handle(MouseEvent event) {
109-
mouseAnchor.set(new Point2D(event.getX(), event.getY()));
110-
rect.setWidth(0);
111-
rect.setHeight(0);
112-
}
113-
});
114-
this.setOnMouseDragged(new EventHandler<MouseEvent>() {
115-
@Override
116-
public void handle(MouseEvent event) {
117-
double x = event.getX();
118-
double y = event.getY();
119-
rect.setX(Math.min(x, mouseAnchor.get().getX()));
120-
rect.setY(Math.min(y, mouseAnchor.get().getY()));
121-
rect.setWidth(Math.abs(x - mouseAnchor.get().getX()));
122-
rect.setHeight(Math.abs(y - mouseAnchor.get().getY()));
123-
}
124-
});
125-
}
126-
127-
public void doZoom(Rectangle zoomRect) {
128-
final NumberAxis yAxis = (NumberAxis) getYAxis();
129-
final NumberAxis xAxis = (NumberAxis) getXAxis();
130-
//Point2D yAxisInScene = yAxis.localToScene(0, 0);
131-
//Point2D xAxisInScene = xAxis.localToScene(0, 0);
132-
double xtopLeftCornerOfGraph = 52;
133-
double ytopLeftCornerOfGraph = 17;
134-
135-
double x = zoomRect.getX() - xtopLeftCornerOfGraph;
136-
double y = zoomRect.getY() - ytopLeftCornerOfGraph;
137-
double w = zoomRect.getWidth();
138-
double h = zoomRect.getHeight();
139-
140-
double width_pixels = this.getWidth() - 65; //65 is the number of pixels of padding
141-
double height_pixels = this.getHeight() - 65;
142-
143-
double width_value = xAxis.getUpperBound() - xAxis.getLowerBound();
144-
double height_value = yAxis.getUpperBound() - yAxis.getLowerBound();
145-
146-
//Point2D zoomTopLeft = new Point2D(zoomRect.getX(), zoomRect.getY());
147-
//Point2D zoomBottomRight = new Point2D(zoomRect.getX() + zoomRect.getWidth(), zoomRect.getY() + zoomRect.getHeight());
148-
//double xOffset = zoomTopLeft.getX() - yAxisInScene.getX();
149-
//double yOffset = zoomBottomRight.getY() - xAxisInScene.getY();
150-
double xAxisScale = width_pixels/width_value;
151-
double yAxisScale = height_pixels/height_value;
152-
153-
double xLower = xAxis.getLowerBound();
154-
double yUpper = yAxis.getUpperBound();
155-
156-
xAxis.setLowerBound(xLower + x / xAxisScale);
157-
xAxis.setUpperBound(xLower + (x+w)/ xAxisScale);
158-
yAxis.setUpperBound(yUpper - y / yAxisScale);
159-
yAxis.setLowerBound(yUpper - (y+h) / yAxisScale);
160-
zoomRect.setWidth(0);
161-
zoomRect.setHeight(0);
162-
}
163-
94+
@Override
16495
public double getLowestX() {
16596
if(this.series.getData().size() == 0) {
16697
return 0;
@@ -169,6 +100,7 @@ public double getLowestX() {
169100
return ((Data<Double,Double>) this.series.getData().get(0)).getXValue();
170101
}
171102

103+
@Override
172104
public double getLowestY() {
173105
if(this.series.getData().size() == 0) {
174106
return 0;
@@ -182,13 +114,15 @@ public double getLowestY() {
182114
return minValue;
183115
}
184116

117+
@Override
185118
public double getHighestX() {
186119
if(this.series.getData().size() == 0) {
187120
return 110;
188121
}
189122
return ((Data<Double,Double>) this.series.getData().get(this.series.getData().size()-1)).getXValue();
190123
}
191124

125+
@Override
192126
public double getHighestY() {
193127
if(this.series.getData().size() == 0) {
194128
return 110;
@@ -202,15 +136,6 @@ public double getHighestY() {
202136
return maxValue;
203137
}
204138

205-
public void setAutoZooming(boolean val) {
206-
getXAxis().setAutoRanging(val);
207-
getYAxis().setAutoRanging(val);
208139

209-
isAutoZooming.set(val);
210-
}
211-
212-
public boolean isAutoZooming() {
213-
return isAutoZooming.get();
214-
}
215140

216141
}

0 commit comments

Comments
 (0)