Updates to the data map for JavaFX

This commit is contained in:
Jamie Mac 2024-07-29 16:04:46 +01:00
parent 9e65fb18f4
commit 7e4ee768d2
4 changed files with 227 additions and 110 deletions

View File

@ -0,0 +1,101 @@
package dataMap.layoutFX;
import java.util.ArrayList;
import PamController.OfflineDataStore;
import PamController.PamController;
import dataMap.DataMapControl;
import dataMap.OfflineDataMap;
import dataMap.OfflineDataMapPoint;
import javafx.scene.paint.Color;
import pamViewFX.fxNodes.pamScrollers.acousticScroller.ScrollBarPane;
/**
* A scroll bar whihc shows a summary fo the data.
*/
public class DataMapScrollPane extends ScrollBarPane {
private DataMapControl dataMapControl;
public DataMapScrollPane(DataMapControl dataMapControl) {
super();
this.dataMapControl=dataMapControl;
}
/**
* Paint a summary of the data
*/
public void paintDataSummary() {
ArrayList<OfflineDataStore> offlineDataStores = PamController.getInstance().findOfflineDataStores();
OfflineDataStore aSource;
Color color = Color.DODGERBLUE;
this.getDrawCanvas().getGraphicsContext2D().setStroke(color);
this.getDrawCanvas().getGraphicsContext2D().setGlobalAlpha(0.3);
for (int i = 0; i < offlineDataStores.size(); i++) {
aSource = offlineDataStores.get(i);
paintOfflineDataSource(aSource);
}
}
/**
* Paint the data on the canvas.
* @param dataSource - the dta source.
*/
private void paintOfflineDataSource(OfflineDataStore dataSource) {
if (dataMapControl.getMappedDataBlocks()==null) return;
OfflineDataMap aMap;
for (int i = 0; i < dataMapControl.getMappedDataBlocks().size(); i++) {
aMap = dataMapControl.getMappedDataBlocks().get(i).getOfflineDataMap(dataSource);
if (aMap == null) {
continue;
}
long lastTime;
OfflineDataMapPoint aPoint;
for (int j=0; j<aMap.getMapPoints().size(); j++) {
aPoint= (OfflineDataMapPoint) aMap.getMapPoints().get(j);
//now have to paint the canvas. To be efficient find the start pixel, then iterate through all the
//the other pixels.
double startPixel = time2Pixel(aPoint.getStartTime());
double endPixel = time2Pixel(aPoint.getEndTime());
for (double k=startPixel; k<endPixel ; k++) {
this.getDrawCanvas().getGraphicsContext2D().strokeLine(k, 0, k, this.getDrawCanvas().getHeight());
}
}
}
}
/**
* Convert a time in millis to a pixel on the canvas.
* @param time
* @return
*/
private double time2Pixel(long time) {
double timeRangemillis = this.getMaxVal() - this.getMinVal();
double frac = ((double) (time - dataMapControl.getFirstTime()))/timeRangemillis;
return frac*this.getDrawCanvas().getWidth();
}
private long pixel2Time(double pixel) {
double frac = pixel/this.getDrawCanvas().getWidth();
double timeRangemillis = this.getMaxVal() - this.getMinVal();
long timeMillis = (long) (frac*timeRangemillis) + dataMapControl.getFirstTime();
return timeMillis;
}
}

View File

@ -242,6 +242,8 @@ public class DataStreamPaneFX extends PamBorderPane {
private DataGraphFX() {
createDataGraph();
addDataGraphMouse();
}
@ -311,6 +313,8 @@ public class DataStreamPaneFX extends PamBorderPane {
//create canvas for overlaid drawings
drawCanvas=new Canvas(90,90);
plotCanvas. getGraphicsContext2D(). setImageSmoothing(false);
Pane pane = new Pane();
pane.getChildren().add(plotCanvas);
pane.getChildren().add(drawCanvas);

View File

@ -24,7 +24,7 @@ import pamViewFX.fxNodes.pamAxis.PamDateAxis;
import pamViewFX.fxNodes.pamScrollers.acousticScroller.ScrollBarPane;
public class ScrollingDataPaneFX extends PamBorderPane {
/**
* Standard millis to wait for repaint.
* Do not ake this too high i.e. above 50 or the display gets very jerky
@ -40,7 +40,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
* Reference to the DataMapControl.
*/
private DataMapControl dataMapControl;
/**
* Reference to the DataMapPaneFX.
*/
@ -50,19 +50,19 @@ public class ScrollingDataPaneFX extends PamBorderPane {
* The scroll pane everything sits in
*/
private PamScrollPane mainScrollPane;
/**
* List of panes- each shows an individual data stream.
*/
private ArrayList<DataStreamPaneFX> dataStreamPanels = new ArrayList<DataStreamPaneFX>();
/**
* Split pane whihc holds different graphs.
*/
private PamVBox dataPanePanes;
private ArrayList<OfflineDataStore> offlineDataStores;
/**
* Time stamp in millis of start of datamap display
*/
@ -72,24 +72,24 @@ public class ScrollingDataPaneFX extends PamBorderPane {
* Time stamp in millis of end of datamap display
*/
private long screenEndMillis = -1;
private double screenSeconds;
/**
* Scroll bar for time (horizontal)
*/
private ScrollBarPane timeScrollBar;
private DataMapScrollPane timeScrollBar;
/**
* Settings strip at top of the display. Shows all sorts of detailed info such cursor position and start and end times.
*/
private SettingsStripFX settingsStrip;
/**
* Shows the start time of the scroll position
*/
private Label scrollEndLabel;
/**
* Shows the end time of the scroll position.
*/
@ -120,13 +120,13 @@ public class ScrollingDataPaneFX extends PamBorderPane {
* @return the scrolling pane.
*/
private Node createScrollingDataPane() {
holder=new PamBorderPane();
//create the main scroll pane
mainScrollPane = new PamScrollPane();
//create the split pane to hold the graphs.
dataPanePanes=new PamVBox();
//dataPanePanes.setOrientation(Orientation.VERTICAL);
@ -135,42 +135,42 @@ public class ScrollingDataPaneFX extends PamBorderPane {
mainScrollPane.setContent(dataPanePanes);
//we have a custom scroll bar for horizontal stuff.
// mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
// ///TEMP///
// Button buttonTest=new Button("Test Map");
// buttonTest.setOnAction((action)->{
// this.dataMapControl.findDataSources();
// });
// holder.setTop(buttonTest);
// //////////
// PamButton test = new PamButton("Test");
// test.setOnAction((action)->{
// updateScrollBar();
// });
// holder.setLeft(test);
// mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
// ///TEMP///
// Button buttonTest=new Button("Test Map");
// buttonTest.setOnAction((action)->{
// this.dataMapControl.findDataSources();
// });
// holder.setTop(buttonTest);
// //////////
// PamButton test = new PamButton("Test");
// test.setOnAction((action)->{
// updateScrollBar();
// });
// holder.setLeft(test);
//finally make sure the scroll bar recalculates stuff when holder changes size
holder.widthProperty().addListener((change)->{
notifyScrollChange(300);
});
dateAxis = new PamDateAxis();
dateAxis.setAutoRanging(false);
dateAxis.setLabel("Time");
dateAxis.setSide(Side.TOP);
dateAxis.setAnimated(false);
dateAxis.setMinHeight(50);
// dateAxis.prefWidthProperty().bind(scrollingDataPanel.widthProperty());
// dateAxis.setStyle("-fx-background-color: ORANGE;");
// dateAxis.prefWidthProperty().bind(scrollingDataPanel.widthProperty());
// dateAxis.setStyle("-fx-background-color: ORANGE;");
dateAxis.setForceZeroInRange(false);
PamVBox vBox = new PamVBox();
vBox.getChildren().add(createScrollBar());
vBox.getChildren().add(dateAxis);
@ -182,7 +182,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
return holder;
}
/**
* Updates the scrollbar.
@ -190,19 +190,19 @@ public class ScrollingDataPaneFX extends PamBorderPane {
public void updateScrollBar() {
setupScrollBar();
updateScrollBarText();
calcStartEndMillis();
updateScrollBarText();
notifyScrollChange();
}
/**
* Create the horizontal scroll bar for scrolling through time.
* @return the horizontal scroll bar.
*/
private PamBorderPane createScrollBar(){
PamBorderPane holder=new PamBorderPane();
//create a pane to show start and end times
PamBorderPane timeLabelPane=new PamBorderPane();
scrollStartLabel=new Label();
@ -213,27 +213,27 @@ public class ScrollingDataPaneFX extends PamBorderPane {
scrollEndLabel.setText(PamCalendar.formatDateTime(screenEndMillis));
timeLabelPane.setPadding(new Insets(2, 10, 2, 10)); //bit of padding to look better
//create the scroll bar and listeners.
timeScrollBar=new ScrollBarPane();
timeScrollBar=new DataMapScrollPane(this.dataMapControl);
timeScrollBar.addValueListener((obs_val, old_val, new_val)->{
System.out.println("Scroll bar seconds: " + timeScrollBar.getCurrentValue() + " vis amount: " + timeScrollBar.visibleAmountProperty().get());
calcStartEndMillis();
updateScrollBarText();
notifyScrollChange();
});
timeScrollBar.getTextBox().setPrefColumnCount(15);
timeScrollBar.getTextBox().setPrefWidth(100);
timeScrollBar.setPrefHeight(50);
holder.setCenter(timeScrollBar);
holder.setBottom(timeLabelPane);
return holder;
}
/**
* Calculate the start and millis based on scroll position and screen seconds.
*/
@ -241,10 +241,10 @@ public class ScrollingDataPaneFX extends PamBorderPane {
screenStartMillis = (long) (dataMapControl.getFirstTime() +
timeScrollBar.getCurrentValue());
screenEndMillis = (long) (screenStartMillis + timeScrollBar.getVisibleAmount());
getPixelsPerHour();
}
/**
* Update the text in the scroll bar. Shows the start and end time of the current screen.
*/
@ -262,13 +262,13 @@ public class ScrollingDataPaneFX extends PamBorderPane {
dataStreamPanels.get(i).scrollChanged();
}
settingsStrip.scrollChanged();
updateDateAxis();
}
Timeline timeline;
long lastTime = 0;
/**
* Notify all panels and the settings strip that the scroll bar moved - but have a timer to wait to not call too often.
*/
@ -286,11 +286,11 @@ public class ScrollingDataPaneFX extends PamBorderPane {
timeline.play();
return;
}
lastTime=currentTime;
updateDateAxis();
}
private void updateDateAxis() {
@ -298,7 +298,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
dateAxis.setUpperBound(screenEndMillis);
dateAxis.setLowerBound(screenStartMillis);
double[] ticks = dateAxis.recalculateTicks();
// System.out.println("Ticks: " + (ticks[3]/1000/3600) + "hours");
// System.out.println("Ticks: " + (ticks[3]/1000/3600) + "hours");
dateAxis.setTickUnit(ticks[3]);
}
@ -307,30 +307,30 @@ public class ScrollingDataPaneFX extends PamBorderPane {
* @return the number of DataStreamPanes created.
*/
public synchronized int createDataGraphs() {
//clear the panes from list and split pane.
dataStreamPanels.clear();
dataPanePanes.getChildren().clear();
//now create new set of data stream panes.
ArrayList<PamDataBlock> dataBlocks = dataMapControl.getMappedDataBlocks();
if (dataBlocks == null) {
System.out.println("DataMapPaneFX:Create Data Graphs: Datablocks are null");
return 0;
}
DataStreamPaneFX aStreamPanel;
for (int i = 0; i < dataBlocks.size(); i++) {
aStreamPanel = new DataStreamPaneFX(dataMapControl, this, dataBlocks.get(i));
dataStreamPanels.add(aStreamPanel);
dataStreamPanels.get(i).setMinHeight(DATASTREAMPANE_HEIGHT);
//now add to a split pane.
//SplitPane.setResizableWithParent(aStreamPanel, true);
dataPanePanes.getChildren().add(aStreamPanel);
//dataPanePanes.setDividerPosition(0,1.0/dataBlocks.size());
}
//clear the panes from list and split pane.
dataStreamPanels.clear();
dataPanePanes.getChildren().clear();
return dataBlocks.size();
//now create new set of data stream panes.
ArrayList<PamDataBlock> dataBlocks = dataMapControl.getMappedDataBlocks();
if (dataBlocks == null) {
System.out.println("DataMapPaneFX:Create Data Graphs: Datablocks are null");
return 0;
}
DataStreamPaneFX aStreamPanel;
for (int i = 0; i < dataBlocks.size(); i++) {
aStreamPanel = new DataStreamPaneFX(dataMapControl, this, dataBlocks.get(i));
dataStreamPanels.add(aStreamPanel);
dataStreamPanels.get(i).setMinHeight(DATASTREAMPANE_HEIGHT);
//now add to a split pane.
//SplitPane.setResizableWithParent(aStreamPanel, true);
dataPanePanes.getChildren().add(aStreamPanel);
//dataPanePanes.setDividerPosition(0,1.0/dataBlocks.size());
}
return dataBlocks.size();
}
/***
* Get the number of panes which are expanded.
@ -354,7 +354,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
createDataGraphs();
setupScrollBar();
}
private void setupScrollBar() {
/**
* Do scrolling in seconds - will give up to 68 years with a
@ -364,33 +364,41 @@ public class ScrollingDataPaneFX extends PamBorderPane {
long dataStart = dataMapControl.getFirstTime();
long dataEnd = dataMapControl.getLastTime();
double dataSeconds = ((dataEnd-dataStart)/1000) + 1;
double pixsPerHour = getPixelsPerHour();
double pixsPerSecond = pixsPerHour / 3600;
double screenWidth = getPlotWidth();
screenSeconds = screenWidth / Math.min(600. / 3600, pixsPerSecond);
// if (dataStart == Long.MAX_VALUE || screenSeconds >= dataSeconds) {
// System.out.println("dataSeconds1: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+ " holder width: "+holder.getWidth());
// /*
// * hide the scroll bar and stretch the display to fit the window
// */
// timeScrollBar.setVisible(true);
// screenStartMillis = dataStart;
// screenEndMillis = dataEnd;
// }
// else {
System.out.println("dataSeconds2: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+" holder width: "+holder.getWidth());
timeScrollBar.setVisible(true);
timeScrollBar.setMinVal(0);
timeScrollBar.setMaxVal(Math.max(dataSeconds, screenSeconds)*1000L);
timeScrollBar.setBlockIncrement(Math.max(1, screenSeconds * 4/5));
// timeScrollBar.setUnitIncrement(Math.max(1, screenSeconds / 20));
timeScrollBar.setVisibleAmount(screenSeconds*1000L);
timeScrollBar.setCurrentValue(currentPos);
// }
// if (dataStart == Long.MAX_VALUE || screenSeconds >= dataSeconds) {
// System.out.println("dataSeconds1: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+ " holder width: "+holder.getWidth());
// /*
// * hide the scroll bar and stretch the display to fit the window
// */
// timeScrollBar.setVisible(true);
// screenStartMillis = dataStart;
// screenEndMillis = dataEnd;
// }
// else {
System.out.println("dataSeconds2: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+" holder width: "+holder.getWidth());
timeScrollBar.setVisible(true);
timeScrollBar.setMinVal(0);
timeScrollBar.setMaxVal(Math.max(dataSeconds, screenSeconds)*1000L);
timeScrollBar.setBlockIncrement(Math.max(1, screenSeconds * 4/5));
// timeScrollBar.setUnitIncrement(Math.max(1, screenSeconds / 20));
timeScrollBar.setVisibleAmount(screenSeconds*1000L);
timeScrollBar.setCurrentValue(currentPos);
//now paint the canvas to show the data.
try {
timeScrollBar.paintDataSummary();
}
catch (Exception e) {
e.printStackTrace();
}
}
@ -401,11 +409,11 @@ public class ScrollingDataPaneFX extends PamBorderPane {
private double getPlotWidth() {
//HACK- seems like there is a lyout delay in datstream panes.
return this.holder.getWidth()-DataStreamPaneFX.axisPrefWidth;
// if (dataStreamPanels.size()>0){
// dataStreamPanels.get(0).layout();
// return dataStreamPanels.get(0).getDataGraph().getPlotWidth();
// }
// return 0;
// if (dataStreamPanels.size()>0){
// dataStreamPanels.get(0).layout();
// return dataStreamPanels.get(0).getDataGraph().getPlotWidth();
// }
// return 0;
}
public void scrollToData(PamDataBlock dataBlock) {
@ -427,14 +435,14 @@ public class ScrollingDataPaneFX extends PamBorderPane {
public long getScreenEndMillis() {
return screenEndMillis;
}
public double getPixelsPerHour() {
System.out.println("Pixels per hour: " + dataMapControl.dataMapParameters.getPixeslPerHour() + " " + this.getPlotWidth()/(this.timeScrollBar.getVisibleAmount()/1000./3600.));
//return dataMapControl.dataMapParameters.getPixeslPerHour();
return this.getPlotWidth()/(this.timeScrollBar.getVisibleAmount()/1000./3600.);
}
/**
@ -443,7 +451,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
public double getScreenSeconds() {
return screenSeconds;
}
/**
* Get a colour for the datastream.
* @param dataSource

View File

@ -312,6 +312,7 @@ public class ScrollBarPane extends PamBorderPane {
rightDrag.getChildren().add(rightdragLine);
rectangle.getChildren().add(rightDrag);
rectangle.setCursor(Cursor.OPEN_HAND); //Change cursor to hand
//now set behaviours
leftDrag.setOnMousePressed((event)->{
@ -366,15 +367,17 @@ public class ScrollBarPane extends PamBorderPane {
});
//now set behaviours
rightDrag.setOnMousePressed((event)->{
rightDrag.setOnMousePressed((event)->{
leftLayoutX=rectangle.getLayoutX();
isChanging.set(true);
rectangle.setCursor(Cursor.CLOSED_HAND); //Change cursor to hand
dragStarted(event, rightDrag);
});
rightDrag.setOnMouseReleased((event)->{
currentValueProperty.setValue(calcScrollBarVal(rectangle.getLayoutX()));
isChanging.set(false);
rectangle.setCursor(Cursor.OPEN_HAND); //Change cursor to hand
dragging(event);
});
@ -426,6 +429,7 @@ public class ScrollBarPane extends PamBorderPane {
rectangle.setOnMouseDragged((event)->{
rectangleDragged(event);
});
return rectangle;
}