mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2024-11-21 22:52:22 +00:00
Updates to delphinID and TDisplayFX
This commit is contained in:
parent
2c8d54b660
commit
83678d3c25
@ -411,6 +411,26 @@ public class PamArrayUtils {
|
||||
|
||||
return new double[] {min, max};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the minimum and maximum value of a 2D array.
|
||||
* @param arr - the array to find the maximum value of.
|
||||
* @return the minimum and maximum value in the array
|
||||
*/
|
||||
public static float[] minmax(float[][] arr) {
|
||||
float max = Float.NEGATIVE_INFINITY;
|
||||
float min = Float.POSITIVE_INFINITY;
|
||||
|
||||
for(int i=0; i<arr.length; i++) {
|
||||
for(int j=0; j<arr[i].length; j++) {
|
||||
max = Math.max(max, arr[i][j]);
|
||||
min = Math.min(min, arr[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
return new float[] {min, max};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -1167,6 +1187,7 @@ public class PamArrayUtils {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -14,7 +14,8 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A series of classes to load and import data stored in text files (includes .csv files)
|
||||
* Some functions to load and import data stored in text files (includes .csv files)
|
||||
*
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
|
@ -1,114 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="150mm"
|
||||
height="150mm"
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="logo01.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.74564394"
|
||||
inkscape:cx="379.53772"
|
||||
inkscape:cy="512.97943"
|
||||
inkscape:window-width="1242"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-x="649"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect3117"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect3117-7"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect3117-6"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:3.175px;fill:#000000;stroke-width:0.264583"
|
||||
x="11.709678"
|
||||
y="81.967743"
|
||||
id="text113"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan111"
|
||||
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:25.4px;font-family:Calibri;-inkscape-font-specification:'Calibri, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
|
||||
x="11.709678"
|
||||
y="81.967743"><tspan
|
||||
style="fill:#6f916f"
|
||||
id="tspan167">delphin</tspan><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:Calibri;-inkscape-font-specification:'Calibri, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#0b2817"
|
||||
id="tspan165">ID</tspan></tspan></text>
|
||||
<path
|
||||
style="fill:#6f916f;stroke-width:0.264583"
|
||||
d="m 27.322579,38.322579 6.741938,2.838712"
|
||||
id="path535" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.85;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 120.67435,61.080456 c 1.55411,1.367612 3.10801,2.735039 4.219,4.735608 1.11098,2.00057 1.77914,4.634082 1.8024,7.356282 0.0232,2.7222 -0.5983,5.53298 -1.65497,7.685367 -1.05667,2.152388 -2.5484,3.646416 -4.0401,5.140414"
|
||||
id="path3115"
|
||||
inkscape:path-effect="#path-effect3117"
|
||||
inkscape:original-d="m 120.67435,61.080456 c 1.55406,1.367671 3.10796,2.735101 4.66173,4.102301 0.66832,2.63386 1.33649,5.26737 2.00453,7.90072 -0.62143,2.81111 -1.24298,5.62189 -1.86469,8.43252 -1.49163,1.49428 -2.98336,2.98831 -4.47524,4.48213" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.85;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 115.99401,66.369877 c 0.93292,0.812059 1.86573,1.624027 2.53264,2.81193 0.66692,1.187903 1.06802,2.751664 1.08197,4.368074 0.014,1.61641 -0.35915,3.285393 -0.99347,4.563459 -0.63431,1.278066 -1.52976,2.165182 -2.42524,3.052317"
|
||||
id="path3115-4"
|
||||
inkscape:path-effect="#path-effect3117-6"
|
||||
inkscape:original-d="m 115.99401,66.369877 c 0.93289,0.81209 1.8657,1.62406 2.79841,2.43588 0.4012,1.56394 0.8023,3.1277 1.20331,4.69134 -0.37304,1.66922 -0.74616,3.3382 -1.11936,5.00712 -0.89543,0.88729 -1.79089,1.7744 -2.68646,2.66144" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.85;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 125.65039,55.168033 c 2.46165,2.066818 4.923,4.133391 6.68278,7.156798 1.75977,3.023407 2.81814,7.003389 2.85497,11.117374 0.0368,4.113986 -0.9477,8.361845 -2.62144,11.614689 -1.67374,3.252844 -4.03659,5.51072 -6.39943,7.768583"
|
||||
id="path3115-8"
|
||||
inkscape:path-effect="#path-effect3117-7"
|
||||
inkscape:original-d="m 125.65039,55.168033 c 2.46157,2.06691 4.92292,4.133487 7.38405,6.199707 1.05862,3.980467 2.11699,7.960447 3.17515,11.940157 -0.98434,4.24836 -1.96886,8.49622 -2.95363,12.74383 -2.36272,2.2583 -4.72558,4.51617 -7.08869,6.77375" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.2 KiB |
@ -137,7 +137,7 @@
|
||||
*/
|
||||
/** top-left, top-right, bottom-right, and bottom-left corners, in that order. */
|
||||
.close-button-right{
|
||||
-fx-background-color: -fx-darkbackground-trans;
|
||||
-fx-background-color: -fx-darkbackground;
|
||||
-fx-background-radius: 0 10 10 0;
|
||||
-fx-border-color: transparent;
|
||||
-fx-border-radius: 0 10 10 0;
|
||||
@ -145,7 +145,7 @@
|
||||
|
||||
|
||||
.close-button-left{
|
||||
-fx-background-color: -fx-darkbackground-trans;
|
||||
-fx-background-color: -fx-darkbackground;
|
||||
-fx-background-radius: 10 0 0 10;
|
||||
-fx-border-color: transparent;
|
||||
-fx-border-radius: 10 0 0 10;
|
||||
@ -153,7 +153,7 @@
|
||||
|
||||
|
||||
.close-button-top{
|
||||
-fx-background-color: -fx-darkbackground-trans;
|
||||
-fx-background-color: -fx-darkbackground;
|
||||
-fx-background-radius: 10 10 0 0;
|
||||
-fx-border-color: transparent;
|
||||
-fx-border-radius: 10 10 0 0;
|
||||
@ -161,7 +161,7 @@
|
||||
|
||||
|
||||
.close-button-bottom{
|
||||
-fx-background-color: -fx-darkbackground-trans;
|
||||
-fx-background-color: -fx-darkbackground;
|
||||
-fx-background-radius: 0 0 10 10;
|
||||
-fx-border-color: transparent;
|
||||
-fx-border-radius: 0 0 10 10;
|
||||
|
@ -115,10 +115,10 @@ public class TDControlFX extends TDControl implements UserDisplayNodeFX {
|
||||
PamDataBlock dataBlock=this.tdDisplayController.getUserDisplayProcess().getParentDataBlock();
|
||||
if (TDDataProviderRegisterFX.getInstance().findDataProvider(dataBlock)!=null) dataBlocks.add(dataBlock);
|
||||
if (dataBlock!=null) {
|
||||
System.out.println("TDControldFX: parent datablock "+dataBlock.getDataName());
|
||||
// System.out.println("TDControldFX: parent datablock "+dataBlock.getDataName());
|
||||
}
|
||||
else{
|
||||
System.out.println("TDControldFX: parent datablock null");
|
||||
// System.out.println("TDControldFX: parent datablock null");
|
||||
return dataBlocks;
|
||||
}
|
||||
|
||||
|
@ -252,10 +252,11 @@ public class TDDisplayFX extends PamBorderPane {
|
||||
//create the button which shows the hiding panel. Although we get this button from the hiding pane, where to place
|
||||
//it and what colour it is etc has to be set for whatever pane it is to be located in.
|
||||
showButton=hidingControlPane.getShowButton();
|
||||
showButton.getStyleClass().add("transparent-button-square");
|
||||
showButton.setStyle("-fx-background-radius: 0 0 10 10;");
|
||||
hidingControlPane.setShowButtonOpacity(1.0);
|
||||
// showButton.getStyleClass().add("transparent-button-square");
|
||||
showButton.setStyle("-fx-background-radius: 0 0 10 0;");
|
||||
showButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-down", PamGuiManagerFX.iconSize));
|
||||
showButton.setPrefWidth(60);
|
||||
showButton.setPrefWidth(30);
|
||||
showButton.setMaxHeight(timeAxisSize-20);
|
||||
|
||||
//create the time axis for the display.
|
||||
@ -276,7 +277,7 @@ public class TDDisplayFX extends PamBorderPane {
|
||||
StackPane mainGraphPane=new StackPane();
|
||||
mainGraphPane.getChildren().add(splitPaneHolder);
|
||||
mainGraphPane.getChildren().add(showButton);
|
||||
StackPane.setAlignment(showButton, Pos.TOP_CENTER);
|
||||
StackPane.setAlignment(showButton, Pos.TOP_LEFT);
|
||||
|
||||
this.setCenter(mainGraphPane);
|
||||
|
||||
|
@ -18,20 +18,25 @@ import javafx.geometry.Pos;
|
||||
import javafx.geometry.Side;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.control.TabPane.TabClosingPolicy;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import pamViewFX.PamGuiManagerFX;
|
||||
import pamViewFX.fxGlyphs.PamGlyphDude;
|
||||
import pamViewFX.fxNodes.PamBorderPane;
|
||||
import pamViewFX.fxNodes.PamButton;
|
||||
import pamViewFX.fxNodes.PamGridPane;
|
||||
import pamViewFX.fxNodes.PamHBox;
|
||||
import pamViewFX.fxNodes.PamStackPane;
|
||||
import pamViewFX.fxNodes.PamTabPane;
|
||||
import pamViewFX.fxNodes.hidingPane.HidingPane;
|
||||
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
|
||||
import pamViewFX.fxStyles.PamStylesManagerFX;
|
||||
|
||||
/**
|
||||
@ -201,6 +206,7 @@ public class DetectionGroupDisplay extends PamBorderPane {
|
||||
|
||||
hidingPane.getShowButton().setGraphic(PamGlyphDude.createPamIcon("mdi2c-cog",
|
||||
PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
hidingPane.setShowButtonOpacity(1.0); //don't want show button to gray out if mouse not over it
|
||||
this.setRight(hidingPane); //bit of a hack but works.
|
||||
hidingPane.showHidePane(false);
|
||||
|
||||
@ -219,36 +225,68 @@ public class DetectionGroupDisplay extends PamBorderPane {
|
||||
detectionDisplayHolder = new PamStackPane();
|
||||
|
||||
PamTabPane settingsPane = new PamTabPane();
|
||||
settingsPane.setTabMinHeight(60);
|
||||
settingsPane.setMinHeight(60);
|
||||
// settingsPane.repackTabs();
|
||||
|
||||
//this has to be before removing the heading button
|
||||
settingsPane.setAddTabButton(false);
|
||||
settingsPane.setTabMinHeight(60);
|
||||
settingsPane.setMinHeight(100);
|
||||
|
||||
// settingsPane.getStyleClass().add(Styles.TABS_FLOATING);
|
||||
settingsPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
|
||||
//settingsPane.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
|
||||
|
||||
Tab dataTab = new Tab("Data",detectionDisplay.getDataTypePane());
|
||||
Tab settingsTab = new Tab("Settings -BLAH",detectionDisplay.getSettingsHolder());
|
||||
PamGridPane gridPane = new PamGridPane();
|
||||
gridPane.setHgap(5.);
|
||||
gridPane.setVgap(5.);
|
||||
gridPane.setPadding(new Insets(0,0,0,5));
|
||||
|
||||
gridPane.add(new Label("Plot type"), 0, 0);
|
||||
gridPane.add(detectionDisplay.getDataTypePane(), 1, 0);
|
||||
|
||||
PamToggleSwitch showScrollSwitch = new PamToggleSwitch("Show scroll bar");
|
||||
showScrollSwitch.selectedProperty().addListener((obsVal, oldVal, newVal)->{
|
||||
//show or hide the scroll bar.
|
||||
this.setEnableScrollBar(newVal);
|
||||
});
|
||||
showScrollSwitch.setSelected(true);
|
||||
gridPane.add(showScrollSwitch, 0, 1);
|
||||
GridPane.setColumnSpan(showScrollSwitch, GridPane.REMAINING);
|
||||
|
||||
|
||||
Tab dataTab = new Tab("Plot",gridPane);
|
||||
|
||||
ScrollPane scrollPane = new ScrollPane();
|
||||
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
|
||||
scrollPane.setContent(detectionDisplay.getSettingsHolder());
|
||||
Tab settingsTab = new Tab("Settings", scrollPane);
|
||||
|
||||
//here add the option to show the scroll bar or not.
|
||||
settingsPane.getTabs().add(dataTab);
|
||||
settingsPane.getTabs().add(settingsTab);
|
||||
|
||||
hidingPane = new HidingPane(Side.RIGHT, settingsPane, detectionDisplayHolder, layoutType==DISPLAY_COMPACT, 0);
|
||||
//set the hiding pane
|
||||
Node icon = PamGlyphDude.createPamIcon("mdi2c-cog", PamGuiManagerFX.iconSize);
|
||||
detectionDisplay.getPlotPane().setHidePane(new PamBorderPane(settingsPane), icon, Side.RIGHT);
|
||||
|
||||
//move the hiding pane button into the top of the tab pane - this makes best
|
||||
//use of space.
|
||||
hidingPane = detectionDisplay.getPlotPane().getHidePane(Side.RIGHT);
|
||||
|
||||
hidingPane.removeHideButton();
|
||||
hidingPane.getHideButton().setMinWidth(40);
|
||||
|
||||
settingsPane.setTabStartRegion(hidingPane.getHideButton());
|
||||
// hidingPane.getHideButton().getStyleClass().add("close-button-right-trans");
|
||||
// hidingPane.getHideButton().setStyle(" -fx-background-radius: 0 0 0 0;");
|
||||
hidingPane.setPadding(new Insets(0,0,0,0));
|
||||
|
||||
hidingPane.getHideButton().prefHeightProperty().bind(settingsPane.tabMinHeightProperty());
|
||||
|
||||
//set the show button to be slight larger
|
||||
hidingPane.getShowButton().setPrefHeight(60.);
|
||||
|
||||
//now everything to pane.
|
||||
detectionDisplayHolder.getChildren().add(detectionDisplay);
|
||||
StackPane.setAlignment(detectionDisplay, Pos.CENTER);
|
||||
|
||||
//settingsPane.setPadding(new Insets(35,0,0,0));
|
||||
|
||||
Node icon = PamGlyphDude.createPamIcon("mdi2c-cog", PamGuiManagerFX.iconSize);
|
||||
detectionDisplay.getPlotPane().setHidePane(new PamBorderPane(settingsPane), icon, Side.RIGHT);
|
||||
hidingPane.getShowButton().setPrefHeight(30);
|
||||
|
||||
}
|
||||
|
||||
//set styles
|
||||
|
@ -6,7 +6,6 @@ import detectionPlotFX.plots.FFTSettingsPane;
|
||||
import javafx.scene.control.ColorPicker;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.Pane;
|
||||
import pamViewFX.fxNodes.PamSpinner;
|
||||
import pamViewFX.fxNodes.PamVBox;
|
||||
import whistlesAndMoans.ConnectedRegionDataUnit;
|
||||
|
||||
|
@ -166,6 +166,8 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
sidePaneContent.setPadding(new Insets(25,5,5,5)); //give quite abit of spacing at the top so that there is room for close button
|
||||
sidePaneContent.setMinWidth(0);
|
||||
hidingSidePane=new HidingPane(Side.RIGHT, sidePaneContent, this, false);
|
||||
hidingSidePane.setShowButtonOpacity(1.0);
|
||||
|
||||
hidingSidePane.showHidePane(false);
|
||||
|
||||
//create the button which shows the hiding panel. Although we get this button from the hiding pane, where to place
|
||||
@ -242,6 +244,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
|
||||
mainTabPane.setTabEndRegion(showButtonRight);
|
||||
mainTabPane.setTabStartRegion(showButtonLeft);
|
||||
// mainTabPane.getStyleClass().add(Styles.TABS_FLOATING);
|
||||
|
||||
mainTabPane.getAddTabButton().setOnAction((value)->{
|
||||
addPamTab(new TabInfo("Display " + (this.getNumTabs()+1)), null ,true);
|
||||
|
@ -103,7 +103,8 @@ public class PamTabPane extends TabPane {
|
||||
public void setAddTabButton(boolean addTabButton) {
|
||||
if (this.addTabButton==addTabButton) return;
|
||||
this.addTabButton = addTabButton;
|
||||
tabPaneSkin = new PamTabPaneSkin(this);
|
||||
// tabPaneSkin = new PamTabPaneSkin(this);
|
||||
tabPaneSkin.setAddTabButton(addTabButton);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,13 +39,13 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
* Button which allows a new tab to be added.
|
||||
*/
|
||||
private PamButton addTabButton;
|
||||
|
||||
|
||||
/**
|
||||
* How many pixels the tab button 'floats' in the header area.
|
||||
*/
|
||||
public double addButtonInsets=3;
|
||||
|
||||
|
||||
|
||||
|
||||
public PamTabPaneSkin(PamTabPane tabPane) {
|
||||
super(tabPane);
|
||||
this.pamTabPane=tabPane;
|
||||
@ -66,7 +66,7 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
|
||||
//add extra regions to header area
|
||||
headerArea.getChildren().add(addTabButton);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -82,7 +82,7 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
public void removeTabEndRegion(Region tabRegion){
|
||||
headerArea.getChildren().remove(tabRegion);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add the tab start region. This sits in the tab header area, either at the left if the tab pane is horizontal or top if the tab pane is vertical.
|
||||
*/
|
||||
@ -114,23 +114,23 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
* Set the add button in the correct position
|
||||
*/
|
||||
private void layoutAddButton(){
|
||||
|
||||
//need to careful here. The width and height of the tab pane don'tr swap on rotation i.e. width of pane remains the axis on which tabs are added.
|
||||
//Weird but guess the java people decided that would make programming easier.
|
||||
double insetx=0.;
|
||||
if (pamTabPane.getSide()==Side.TOP || pamTabPane.getSide()==Side.BOTTOM){
|
||||
addTabButton.layoutXProperty().setValue(tabContentArea.getWidth()+insetx+headerArea.getPadding().getLeft()+addButtonInsets);
|
||||
addTabButton.layoutYProperty().setValue(headerArea.getHeight()-tabContentArea.getHeight()+addButtonInsets);
|
||||
addTabButton.resize(tabContentArea.getHeight()-4, tabContentArea.getHeight()-addButtonInsets*2);
|
||||
}
|
||||
else{
|
||||
//yep, this makes no sense but works when tabs are vertical.
|
||||
addTabButton.layoutXProperty().setValue(headerArea.getWidth()-tabContentArea.getWidth()-tabContentArea.getHeight()-headerArea.getPadding().getTop());
|
||||
addTabButton.layoutYProperty().setValue(headerArea.getHeight()-tabContentArea.getHeight());
|
||||
addTabButton.resize(tabContentArea.getHeight(),tabContentArea.getHeight());
|
||||
}
|
||||
|
||||
// System.out.println("tab Content area width: " +tabContentArea.getWidth()+" tab Content area height: "+tabContentArea.getHeight()+ " addTabButton.layoutYProperty()" +addTabButton.layoutYProperty().getValue());
|
||||
|
||||
//need to careful here. The width and height of the tab pane don'tr swap on rotation i.e. width of pane remains the axis on which tabs are added.
|
||||
//Weird but guess the java people decided that would make programming easier.
|
||||
double insetx=0.;
|
||||
if (pamTabPane.getSide()==Side.TOP || pamTabPane.getSide()==Side.BOTTOM){
|
||||
addTabButton.layoutXProperty().setValue(tabContentArea.getWidth()+insetx+headerArea.getPadding().getLeft()+addButtonInsets);
|
||||
addTabButton.layoutYProperty().setValue(headerArea.getHeight()-tabContentArea.getHeight()+addButtonInsets);
|
||||
addTabButton.resize(tabContentArea.getHeight()-4, tabContentArea.getHeight()-addButtonInsets*2);
|
||||
}
|
||||
else{
|
||||
//yep, this makes no sense but works when tabs are vertical.
|
||||
addTabButton.layoutXProperty().setValue(headerArea.getWidth()-tabContentArea.getWidth()-tabContentArea.getHeight()-headerArea.getPadding().getTop());
|
||||
addTabButton.layoutYProperty().setValue(headerArea.getHeight()-tabContentArea.getHeight());
|
||||
addTabButton.resize(tabContentArea.getHeight(),tabContentArea.getHeight());
|
||||
}
|
||||
|
||||
// System.out.println("tab Content area width: " +tabContentArea.getWidth()+" tab Content area height: "+tabContentArea.getHeight()+ " addTabButton.layoutYProperty()" +addTabButton.layoutYProperty().getValue());
|
||||
|
||||
}
|
||||
|
||||
@ -153,24 +153,24 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
double startHeaderSize;
|
||||
double endHeadersize;
|
||||
if (pamTabPane.getSide()==Side.TOP || pamTabPane.getSide()==Side.BOTTOM){
|
||||
startHeaderSize = (pamTabPane.getTabStartRegion()==null) ? in.getLeft() : getRegionWidth(pamTabPane.getTabStartRegion());
|
||||
endHeadersize = (pamTabPane.getTabEndRegion()==null) ? in.getRight(): getRegionWidth(pamTabPane.getTabEndRegion());
|
||||
//set padding of tab header to make space for any added buttons
|
||||
headerArea.setPadding(new Insets(
|
||||
in.getTop(),
|
||||
endHeadersize,
|
||||
in.getBottom(),
|
||||
startHeaderSize));
|
||||
startHeaderSize = (pamTabPane.getTabStartRegion()==null) ? in.getLeft() : getRegionWidth(pamTabPane.getTabStartRegion());
|
||||
endHeadersize = (pamTabPane.getTabEndRegion()==null) ? in.getRight(): getRegionWidth(pamTabPane.getTabEndRegion());
|
||||
//set padding of tab header to make space for any added buttons
|
||||
headerArea.setPadding(new Insets(
|
||||
in.getTop(),
|
||||
endHeadersize,
|
||||
in.getBottom(),
|
||||
startHeaderSize));
|
||||
}
|
||||
else {
|
||||
startHeaderSize = (pamTabPane.getTabStartRegion()==null) ? in.getTop() : pamTabPane.getTabStartRegion().getHeight();
|
||||
endHeadersize = (pamTabPane.getTabEndRegion()==null) ? in.getBottom(): pamTabPane.getTabEndRegion().getHeight();
|
||||
//set padding of tab header to make space for any added buttons
|
||||
headerArea.setPadding(new Insets(
|
||||
startHeaderSize,
|
||||
in.getRight(),
|
||||
endHeadersize,
|
||||
in.getLeft()));
|
||||
startHeaderSize = (pamTabPane.getTabStartRegion()==null) ? in.getTop() : pamTabPane.getTabStartRegion().getHeight();
|
||||
endHeadersize = (pamTabPane.getTabEndRegion()==null) ? in.getBottom(): pamTabPane.getTabEndRegion().getHeight();
|
||||
//set padding of tab header to make space for any added buttons
|
||||
headerArea.setPadding(new Insets(
|
||||
startHeaderSize,
|
||||
in.getRight(),
|
||||
endHeadersize,
|
||||
in.getLeft()));
|
||||
}
|
||||
|
||||
//layout additional header regions for start
|
||||
@ -210,14 +210,14 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
//System.out.println("Hello "+hello.getWidth()+" "+headerArea.getWidth()+ " "+tabContentArea.getWidth());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private double getRegionWidth(Region region){
|
||||
double regionWidth=50;
|
||||
if (region.getMinWidth()>0) regionWidth=region.getMinWidth();
|
||||
if (region.getPrefWidth()>0) regionWidth=region.getPrefWidth();
|
||||
return regionWidth;
|
||||
}
|
||||
|
||||
|
||||
private double getRegionHeight(Region region){
|
||||
double regionHeight=50;
|
||||
if (region.getMinHeight()>0) regionHeight=region.getMinHeight();
|
||||
@ -240,7 +240,7 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
public double getHeaderHeight() {
|
||||
return headerArea.getHeight();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the height property of the header.
|
||||
* @return the height property of the header.
|
||||
@ -248,6 +248,20 @@ public class PamTabPaneSkin extends TabPaneSkin {
|
||||
public ReadOnlyDoubleProperty getHeaderHeightProperty(){
|
||||
return headerArea.heightProperty();
|
||||
}
|
||||
|
||||
|
||||
public void setAddTabButton(boolean addTabButton2) {
|
||||
if (addTabButton2){
|
||||
if (!headerArea.getChildren().contains(addTabButton)) {
|
||||
headerArea.getChildren().remove(addTabButton);
|
||||
layoutAddButton();
|
||||
}
|
||||
}
|
||||
else {
|
||||
headerArea.getChildren().remove(addTabButton);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ public class PamFlipPane extends FlipPane {
|
||||
backButton.setStyle("-fx-background-radius: 0 5 5 0; -fx-border-radius: 0 5 5 0; -fx-background-color: -color-accent-6");
|
||||
|
||||
backButton.setOnAction((action)->{
|
||||
System.out.println("FLIP BACK TO FRONT");
|
||||
// System.out.println("FLIP BACK TO FRONT");
|
||||
this.backButtonResponse.setValue(OK_BACK_BUTTON);
|
||||
this.flipToFront();
|
||||
});
|
||||
|
@ -13,12 +13,14 @@ import javafx.util.Duration;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.animation.Animation.Status;
|
||||
import javafx.beans.binding.DoubleBinding;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
/**
|
||||
* Hiding pane which can be added to any node.
|
||||
@ -32,6 +34,12 @@ import javafx.event.EventHandler;
|
||||
*/
|
||||
public class HidingPane extends StackPane {
|
||||
|
||||
/**
|
||||
* The opacity of the button when the mouse is outside the show button
|
||||
*/
|
||||
private double showButtonOpacity = 0.25;
|
||||
|
||||
|
||||
/**
|
||||
* Which side the pane is hiding on.
|
||||
*/
|
||||
@ -52,7 +60,7 @@ public class HidingPane extends StackPane {
|
||||
* width when shown and when aligned top.button it is the height shown.
|
||||
*/
|
||||
private double expandedSize=300;
|
||||
|
||||
|
||||
/**
|
||||
* Show/Hide animation time in milliseconds.
|
||||
*/
|
||||
@ -72,7 +80,7 @@ public class HidingPane extends StackPane {
|
||||
* Button which sits in the hiding pane. Pressed to hide pane.
|
||||
*/
|
||||
private PamButton hideButton;
|
||||
|
||||
|
||||
/**
|
||||
* The button which shows the pane. This button isn't actually on the pane.
|
||||
*/
|
||||
@ -93,22 +101,22 @@ public class HidingPane extends StackPane {
|
||||
* The translate property, depends on side and whether the hiding panel is overlaid or moves it's parent node.
|
||||
*/
|
||||
private DoubleProperty paneTanslateProperty;
|
||||
|
||||
|
||||
/**
|
||||
* The binding property for the show button. Only used when the panel is overlayed on another panel.
|
||||
*/
|
||||
private DoubleBinding buttonTranslateProperty;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the panel is showing or not;
|
||||
*/
|
||||
private BooleanProperty showing=new SimpleBooleanProperty(false);
|
||||
|
||||
|
||||
/**
|
||||
* If true then the pane only shows once the hide pane animation has finished
|
||||
*/
|
||||
private boolean visibleImmediatly=true;
|
||||
|
||||
|
||||
/**
|
||||
* The default size of the icons
|
||||
*/
|
||||
@ -119,7 +127,7 @@ public class HidingPane extends StackPane {
|
||||
*
|
||||
*/
|
||||
private double offset=0;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor top create a new hiding pane.
|
||||
* @param side - the side the hiding pane appears from.
|
||||
@ -134,14 +142,14 @@ public class HidingPane extends StackPane {
|
||||
this.holderPane=holderPane;
|
||||
this.overlay=overlay;
|
||||
this.offset=offset;
|
||||
|
||||
// //CSS styling
|
||||
// this.getStylesheets().add(getClass().getResource("pamSettingsCSS.css").toExternalForm());
|
||||
// this.getStyleClass().add("pane");
|
||||
|
||||
|
||||
// //CSS styling
|
||||
// this.getStylesheets().add(getClass().getResource("pamSettingsCSS.css").toExternalForm());
|
||||
// this.getStyleClass().add("pane");
|
||||
|
||||
//set the size the panel will expand to
|
||||
setDefaultExpandedSize(hidePane);
|
||||
|
||||
|
||||
//set the translate property and side index.
|
||||
setTranlsateProperty();
|
||||
|
||||
@ -150,36 +158,36 @@ public class HidingPane extends StackPane {
|
||||
styleHideButton(hideButton);
|
||||
hideButton.setOnAction(new HideButtonPressed());
|
||||
hideButton.setVisible(false);
|
||||
// hideButton.setStyle("close-button-right");
|
||||
// hideButton.setStyle("close-button-right");
|
||||
|
||||
//create a show button. The show button is not displayed on the hiding panel but caqn be used in other panels
|
||||
showButton=createShowButton(true);
|
||||
|
||||
|
||||
//if overlay true bind the show button to the side pane.
|
||||
if (overlay) showButton.translateXProperty().bind(buttonTranslateProperty);
|
||||
|
||||
|
||||
//set up the animation for panel showing/hiding
|
||||
setAnimation();
|
||||
|
||||
|
||||
holderPane.setMinHeight(5); //needed for hiding panes to appear outside holder pane.
|
||||
|
||||
|
||||
// this.setMinHeight(500);
|
||||
// holderPane.heightProperty().addListener((oldVall, newVal, obsVsal)->{
|
||||
// if (this.getHeight()<500){
|
||||
// this.setLayoutY(0);
|
||||
// this.setMinHeight(500);
|
||||
// holderPane.setStyle("-fx-background: red;");
|
||||
// }
|
||||
// System.out.println("HidingPane: LayoutY: "+this.getLayoutY() + " height "+this.getHeight());
|
||||
// });
|
||||
|
||||
// PamBorderPane mainPane=new PamBorderPane();
|
||||
// mainPane.setCenter(hidePane);
|
||||
|
||||
|
||||
|
||||
// this.setMinHeight(500);
|
||||
// holderPane.heightProperty().addListener((oldVall, newVal, obsVsal)->{
|
||||
// if (this.getHeight()<500){
|
||||
// this.setLayoutY(0);
|
||||
// this.setMinHeight(500);
|
||||
// holderPane.setStyle("-fx-background: red;");
|
||||
// }
|
||||
// System.out.println("HidingPane: LayoutY: "+this.getLayoutY() + " height "+this.getHeight());
|
||||
// });
|
||||
|
||||
// PamBorderPane mainPane=new PamBorderPane();
|
||||
// mainPane.setCenter(hidePane);
|
||||
|
||||
this.getChildren().add(hidePane);
|
||||
setHideButtonPos(side);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -193,36 +201,36 @@ public class HidingPane extends StackPane {
|
||||
public HidingPane(final Side side, Region hidePane, Pane holderPane, boolean overlay) {
|
||||
this(side, hidePane, holderPane, overlay, 0);
|
||||
}
|
||||
|
||||
|
||||
public void setShowButton(PamButton showButton) {
|
||||
this.showButton = showButton;
|
||||
}
|
||||
|
||||
|
||||
public boolean isHorizontal(){
|
||||
if (side==Side.TOP || side==Side.BOTTOM) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void resetHideAnimation(){
|
||||
//set the size the panel will expand to
|
||||
setDefaultExpandedSize(hidePane);
|
||||
|
||||
|
||||
//set the translate property and side index.
|
||||
setTranlsateProperty();
|
||||
//set up the animation for panel showing/hiding
|
||||
setAnimation();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Style the button to have an image of arrow.
|
||||
* @param button-button to style
|
||||
*/
|
||||
public void styleHideButton(PamButton button){
|
||||
styleHideButton(button, side);
|
||||
styleHideButton(button, side);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Style the button to have an image of arrow.
|
||||
* @param button-button to style
|
||||
@ -232,34 +240,34 @@ public class HidingPane extends StackPane {
|
||||
switch (side){
|
||||
case RIGHT:
|
||||
//button.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("/Resources/SidePanelShow2.png"))));
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_RIGHT, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_RIGHT, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
button.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-right", PamGuiManagerFX.iconSize));
|
||||
button.getStyleClass().add("close-button-right");
|
||||
break;
|
||||
case LEFT:
|
||||
//button.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("/Resources/SidePanelHide2.png"))));
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_LEFT, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_LEFT, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
button.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", PamGuiManagerFX.iconSize));
|
||||
button.getStyleClass().add("close-button-left");
|
||||
break;
|
||||
case TOP:
|
||||
//button.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("/Resources/SidePanelUp2.png"))));
|
||||
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_UP, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_UP, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
button.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-up", PamGuiManagerFX.iconSize));
|
||||
button.setPrefWidth(60); //horizontal buttons are slightly wider
|
||||
button.getStyleClass().add("close-button-top");
|
||||
break;
|
||||
case BOTTOM:
|
||||
//utton.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("/Resources/SidePanelDown2.png"))));
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_DOWN, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
// button.setGraphic(PamGlyphDude.createPamGlyph(FontAwesomeIcon.CHEVRON_DOWN, PamGuiManagerFX.iconColor, PamGuiManagerFX.iconSize));
|
||||
button.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-down", PamGuiManagerFX.iconSize));
|
||||
button.setPrefWidth(60); //horizontal buttons are slightly wider
|
||||
button.getStyleClass().add("close-button-bottom");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the default expanded size for the hiding panel. If the pane has a preferred size then uses this but if not then uses
|
||||
* the field expandedSize to set expanded Size;
|
||||
@ -267,11 +275,11 @@ public class HidingPane extends StackPane {
|
||||
*/
|
||||
private void setDefaultExpandedSize(Region hidePane){
|
||||
boolean isHorizontal=isHorizontal();
|
||||
|
||||
|
||||
//check if the panel has a preferred width or height depending on side position. If so set the expanded size to that;
|
||||
if (!isHorizontal && hidePane.getPrefWidth()>0) expandedSize=hidePane.getPrefWidth();
|
||||
else if (isHorizontal && hidePane.getPrefHeight()>0) expandedSize=hidePane.getPrefHeight();
|
||||
|
||||
|
||||
//now set the correct preferred width for the panel
|
||||
if (!isHorizontal){
|
||||
hidePane.setPrefWidth(expandedSize);
|
||||
@ -285,7 +293,7 @@ public class HidingPane extends StackPane {
|
||||
this.setMinWidth(0);
|
||||
this.setMinHeight(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the preferred size is set for the hiding pane then the expanded size, the animation, the show
|
||||
* button binding property and position of the pane must be reset.
|
||||
@ -313,9 +321,9 @@ public class HidingPane extends StackPane {
|
||||
//set the correct translation for the pane
|
||||
if (showing.get()) paneTanslateProperty.set(overlay ? 0 : expandedSize+offset);
|
||||
else paneTanslateProperty.set(overlay ? (expandedSize+offset)*sideIndex: 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a blank button which contains all the functionality to open or close the hiding panel, including the ability
|
||||
@ -328,75 +336,95 @@ public class HidingPane extends StackPane {
|
||||
|
||||
|
||||
private PamButton createShowButton(final boolean show){
|
||||
|
||||
final PamButton pamButton=new PamButton();
|
||||
|
||||
pamButton.setOnMousePressed(new EventHandler<MouseEvent>() {
|
||||
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// record a delta distance for the drag and drop operation.
|
||||
dragX =mouseEvent.getSceneX();
|
||||
dragY =mouseEvent.getSceneY();
|
||||
}
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// record a delta distance for the drag and drop operation.
|
||||
dragX =mouseEvent.getSceneX();
|
||||
dragY =mouseEvent.getSceneY();
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
if (distance==0) return;
|
||||
distance=sideIndex*distance;
|
||||
// System.out.println("Mouse released: HidePanel distance: "+distance);
|
||||
if (!overlay) distance=Math.abs(distance);
|
||||
//need to see where the drag has ended-if greater than 50% then open but if less then close.
|
||||
if (!isHorizontal()){
|
||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
||||
}
|
||||
else{
|
||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
||||
}
|
||||
//reset the distance
|
||||
distance=0;
|
||||
}
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
if (distance==0) return;
|
||||
distance=sideIndex*distance;
|
||||
// System.out.println("Mouse released: HidePanel distance: "+distance);
|
||||
if (!overlay) distance=Math.abs(distance);
|
||||
//need to see where the drag has ended-if greater than 50% then open but if less then close.
|
||||
if (!isHorizontal()){
|
||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
||||
}
|
||||
else{
|
||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
||||
}
|
||||
//reset the distance
|
||||
distance=0;
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseDragged(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
if (visibleImmediatly) hidePane.setVisible(true);
|
||||
else hidePane.setVisible(false);
|
||||
// hideButton.setVisible(true);
|
||||
/**
|
||||
* Work out the distance the panel is to be dragged;
|
||||
*/
|
||||
if (!isHorizontal()){
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
if (visibleImmediatly) hidePane.setVisible(true);
|
||||
else hidePane.setVisible(false);
|
||||
// hideButton.setVisible(true);
|
||||
/**
|
||||
* Work out the distance the panel is to be dragged;
|
||||
*/
|
||||
if (!isHorizontal()){
|
||||
if (!show) distance=(mouseEvent.getSceneX()-dragX);
|
||||
else distance=(mouseEvent.getSceneX()-dragX)+sideIndex*expandedSize;
|
||||
if (!overlay) distance=expandedSize-sideIndex*distance;
|
||||
}
|
||||
else{
|
||||
}
|
||||
else{
|
||||
if (!show) distance=(mouseEvent.getSceneY()-dragY);
|
||||
else distance=(mouseEvent.getSceneY()-dragY)-sideIndex*expandedSize;
|
||||
if (!overlay) distance=expandedSize+sideIndex*distance;
|
||||
}
|
||||
// if (show && Math.abs(distance)>expandedSize) return;
|
||||
|
||||
translatePanel(distance);
|
||||
}
|
||||
});
|
||||
pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
}
|
||||
});
|
||||
pamButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
//System.out.println("Mouse clicked");
|
||||
showHidePane(show);
|
||||
}
|
||||
});
|
||||
pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
//System.out.println("Button event");
|
||||
showHidePane(show);
|
||||
}
|
||||
}
|
||||
// if (show && Math.abs(distance)>expandedSize) return;
|
||||
|
||||
translatePanel(distance);
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse entered");
|
||||
pamButton.setOpacity(1.0);
|
||||
pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse exited");
|
||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
||||
}
|
||||
});
|
||||
|
||||
// pamButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse clicked");
|
||||
// showHidePane(show);
|
||||
// }
|
||||
// });
|
||||
|
||||
pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
System.out.println("HidingPane.showButton - action event clicked");
|
||||
showHidePane(show);
|
||||
}
|
||||
});
|
||||
|
||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
|
||||
return pamButton;
|
||||
}
|
||||
|
||||
@ -425,21 +453,21 @@ public class HidingPane extends StackPane {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the hide button from the hiding pane. For example, used if the pane is non user controllable.
|
||||
*/
|
||||
public void removeHideButton(){
|
||||
this.getChildren().remove(hideButton);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The hiding panel will have a different side Index and translateProperty depending on what the side and overlay value combination is.
|
||||
* This function sets the correct values for sideIndex and translateProperty which are used in opening/closing animations and dragging the panel to an open or c
|
||||
* closed position.
|
||||
*/
|
||||
private void setTranlsateProperty(){
|
||||
|
||||
|
||||
/**
|
||||
* Figure out the correct index and property. The sideIndex is used to tell the animation what direction to
|
||||
* move the animation in. The property tells the panel either to translate in the x or y direction or
|
||||
@ -481,7 +509,7 @@ public class HidingPane extends StackPane {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a time line to show or hide a pane.
|
||||
* @param paneTanslateProperty -the translate property e.g. whether to change the preferred height/width, max height/width etc.
|
||||
@ -494,18 +522,18 @@ public class HidingPane extends StackPane {
|
||||
// Animation for scroll SHOW.
|
||||
timeLine.setCycleCount(1); //defines the number of cycles for this animation
|
||||
final KeyValue kvDwn = new KeyValue(paneTanslateProperty, newSize);
|
||||
// final KeyValue kvDwn = new KeyValue(translateProperty, expandedSize);
|
||||
// final KeyValue kvDwn = new KeyValue(translateProperty, expandedSize);
|
||||
final KeyFrame kfDwn = new KeyFrame(Duration.millis(duration), kvDwn);
|
||||
timeLine.getKeyFrames().add(kfDwn);
|
||||
return timeLine;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set up the animation that moves the hiding panel to show and to hide. translate property and sideIndex must be set
|
||||
* before calling this function.
|
||||
*/
|
||||
private void setAnimation(){
|
||||
|
||||
|
||||
//Initially hiding the pane
|
||||
paneTanslateProperty.set((expandedSize)*sideIndex); //+for right
|
||||
|
||||
@ -514,23 +542,23 @@ public class HidingPane extends StackPane {
|
||||
timeLineShow = createAnimation(paneTanslateProperty, overlay ? 0-offset : expandedSize +offset , duration);
|
||||
// Animation for scroll HIDE
|
||||
timeLineHide = createAnimation(paneTanslateProperty, overlay ? (expandedSize +offset)*sideIndex: 0-offset , duration);
|
||||
|
||||
|
||||
timeLineShow.setOnFinished(new EventHandler<ActionEvent>(){
|
||||
@Override
|
||||
public void handle(ActionEvent arg0) {
|
||||
showFinished();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void handle(ActionEvent arg0) {
|
||||
showFinished();
|
||||
}
|
||||
});
|
||||
|
||||
timeLineHide.setOnFinished(new EventHandler<ActionEvent>(){
|
||||
@Override
|
||||
public void handle(ActionEvent arg0) {
|
||||
hideFinished();
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void handle(ActionEvent arg0) {
|
||||
hideFinished();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called whenever the hid animation has finished.
|
||||
*/
|
||||
@ -540,12 +568,12 @@ public class HidingPane extends StackPane {
|
||||
hidePane.setVisible(false);
|
||||
hideButton.setVisible(false);
|
||||
showButton.toFront();
|
||||
// //TODO-delete
|
||||
// System.out.println("ShowButton Size:"+showButton.getLayoutX() +" tranlateX: "+showButton.getTranslateX() +
|
||||
// " tranlateY: "+showButton.getTranslateY()+" show button layoutX "+ showButton.getLayoutX()+ " "
|
||||
// +showButton.getLayoutY()+ "show button width: "+showButton.getWidth());
|
||||
// //TODO-delete
|
||||
// System.out.println("ShowButton Size:"+showButton.getLayoutX() +" tranlateX: "+showButton.getTranslateX() +
|
||||
// " tranlateY: "+showButton.getTranslateY()+" show button layoutX "+ showButton.getLayoutX()+ " "
|
||||
// +showButton.getLayoutY()+ "show button width: "+showButton.getWidth());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called whenever the show animation has finished.
|
||||
*/
|
||||
@ -554,7 +582,7 @@ public class HidingPane extends StackPane {
|
||||
hidePane.setVisible(true);
|
||||
hideButton.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move the hiding panel to show or hide a certain distance.
|
||||
* @param distance. The distance in pixels to move the panel. Positive to open the panel and negative to move the panel towards closed.
|
||||
@ -562,12 +590,12 @@ public class HidingPane extends StackPane {
|
||||
public void translatePanel(double distance){
|
||||
paneTanslateProperty.set(distance);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show or hide the pane.
|
||||
* @param showing-
|
||||
*/
|
||||
public void showHidePane(boolean show){
|
||||
public synchronized void showHidePane(boolean show){
|
||||
if (show) {
|
||||
//the pref size may have been changed...hide pane shoulf follow this size.
|
||||
showing.setValue(true);
|
||||
@ -575,6 +603,11 @@ public class HidingPane extends StackPane {
|
||||
//hideButton.setVisible(true);
|
||||
//System.out.println("HidingPane: Open Hide Pane");
|
||||
//open the panel
|
||||
if (timeLineShow.getStatus()==Status.RUNNING) {
|
||||
//stops the issue with the hiding pane freezing.
|
||||
return;
|
||||
}
|
||||
|
||||
timeLineShow.play();
|
||||
}
|
||||
else{
|
||||
@ -585,7 +618,7 @@ public class HidingPane extends StackPane {
|
||||
timeLineHide.play();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the hide pane
|
||||
* @param show - tru to opne the pane. False to close the pnae
|
||||
@ -604,7 +637,7 @@ public class HidingPane extends StackPane {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called whenever the pin button is pressed.
|
||||
* @author Jamie Macaulay
|
||||
@ -624,7 +657,7 @@ public class HidingPane extends StackPane {
|
||||
public PamButton getHideButton() {
|
||||
return hideButton;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the button which shows the hide pane. This is generally not on the pane itself but needs to be
|
||||
* added to another pane.
|
||||
@ -649,7 +682,7 @@ public class HidingPane extends StackPane {
|
||||
public void setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the pane which contains this hiding pane.
|
||||
* @return the pane the hiding pane is located in.
|
||||
@ -657,7 +690,7 @@ public class HidingPane extends StackPane {
|
||||
public Pane getHolderPane() {
|
||||
return holderPane;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the timeline which opens hiding tab pane.
|
||||
* @return TimelIne which opens the hiding pane.
|
||||
@ -673,7 +706,7 @@ public class HidingPane extends StackPane {
|
||||
public Timeline getTimeLineHide() {
|
||||
return timeLineHide;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the hide pane shows content at the start of the hide animation or end.
|
||||
@ -682,7 +715,7 @@ public class HidingPane extends StackPane {
|
||||
public boolean isVisibleImmediatly() {
|
||||
return visibleImmediatly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether the hide pane shows content at the start of the hide animation or end.
|
||||
* @param true if shows the pane at the start of the animation.
|
||||
@ -690,7 +723,7 @@ public class HidingPane extends StackPane {
|
||||
public void setVisibleImmediatly(boolean visibleImmediatly) {
|
||||
this.visibleImmediatly = visibleImmediatly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The showing property for the hiding pane.
|
||||
* @return the showing property
|
||||
@ -698,53 +731,71 @@ public class HidingPane extends StackPane {
|
||||
public BooleanProperty showingProperty(){
|
||||
return this.showing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the opacity of the show button when the mouse is outside the button.
|
||||
* @return the opacity of the show button.
|
||||
*/
|
||||
public double getShowButtonOpacity() {
|
||||
return showButtonOpacity;
|
||||
}
|
||||
|
||||
|
||||
// hideSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
|
||||
// @Override public void handle(ActionEvent actionEvent) {
|
||||
// setVisible(false);
|
||||
// controlButton.setText("Show");
|
||||
// controlButton.getStyleClass().remove("hide-left");
|
||||
// controlButton.getStyleClass().add("show-right");
|
||||
// }
|
||||
//});
|
||||
//
|
||||
//
|
||||
//showSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
|
||||
// @Override public void handle(ActionEvent actionEvent) {
|
||||
// controlButton.setText("Collapse");
|
||||
// controlButton.getStyleClass().add("hide-left");
|
||||
// controlButton.getStyleClass().remove("show-right");
|
||||
// }
|
||||
//});
|
||||
|
||||
// // create an animation to hide sidebar.
|
||||
// final Animation hideSidebar = new Transition() {
|
||||
// { setCycleDuration(Duration.millis(50)); }
|
||||
// protected void interpolate(double frac) {
|
||||
// final double curWidth = expandedWidth * (1.0 - frac);
|
||||
// setPrefWidth(curWidth);
|
||||
// setTranslateX(curWidth);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // create an animation to show a sidebar.
|
||||
// final Animation showSidebar = new Transition() {
|
||||
// { setCycleDuration(Duration.millis(duration)); }
|
||||
// protected void interpolate(double frac) {
|
||||
// final double curWidth = expandedWidth * frac;
|
||||
// setPrefWidth(curWidth);
|
||||
// setTranslateX(expandedWidth-curWidth);
|
||||
// }
|
||||
// };
|
||||
|
||||
// if (showSidebar.statusProperty().get() == Animation.Status.STOPPED && hideSidebar.statusProperty().get() == Animation.Status.STOPPED) {
|
||||
// if (isVisible()) {
|
||||
// hideSidebar.play();
|
||||
// } else {
|
||||
// setVisible(true);
|
||||
// showSidebar.play();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Set the opacity of the show button when the mouse is outside.
|
||||
* @return the opacity of the show button - set to 1.0 for no chnage when mouse outside the button.
|
||||
*/
|
||||
public void setShowButtonOpacity(double showButtonOpacity) {
|
||||
this.showButtonOpacity = showButtonOpacity;
|
||||
this.showButton.setOpacity(showButtonOpacity);
|
||||
}
|
||||
|
||||
|
||||
// hideSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
|
||||
// @Override public void handle(ActionEvent actionEvent) {
|
||||
// setVisible(false);
|
||||
// controlButton.setText("Show");
|
||||
// controlButton.getStyleClass().remove("hide-left");
|
||||
// controlButton.getStyleClass().add("show-right");
|
||||
// }
|
||||
//});
|
||||
//
|
||||
//
|
||||
//showSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
|
||||
// @Override public void handle(ActionEvent actionEvent) {
|
||||
// controlButton.setText("Collapse");
|
||||
// controlButton.getStyleClass().add("hide-left");
|
||||
// controlButton.getStyleClass().remove("show-right");
|
||||
// }
|
||||
//});
|
||||
|
||||
// // create an animation to hide sidebar.
|
||||
// final Animation hideSidebar = new Transition() {
|
||||
// { setCycleDuration(Duration.millis(50)); }
|
||||
// protected void interpolate(double frac) {
|
||||
// final double curWidth = expandedWidth * (1.0 - frac);
|
||||
// setPrefWidth(curWidth);
|
||||
// setTranslateX(curWidth);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // create an animation to show a sidebar.
|
||||
// final Animation showSidebar = new Transition() {
|
||||
// { setCycleDuration(Duration.millis(duration)); }
|
||||
// protected void interpolate(double frac) {
|
||||
// final double curWidth = expandedWidth * frac;
|
||||
// setPrefWidth(curWidth);
|
||||
// setTranslateX(expandedWidth-curWidth);
|
||||
// }
|
||||
// };
|
||||
|
||||
// if (showSidebar.statusProperty().get() == Animation.Status.STOPPED && hideSidebar.statusProperty().get() == Animation.Status.STOPPED) {
|
||||
// if (isVisible()) {
|
||||
// hideSidebar.play();
|
||||
// } else {
|
||||
// setVisible(true);
|
||||
// showSidebar.play();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
@ -213,9 +213,7 @@ public class PamHiddenSidePane extends PamStackPane {
|
||||
break;
|
||||
}
|
||||
|
||||
//make show button same height as hide button
|
||||
// showButton.prefHeightProperty().bind(hidingPane.getHideButton().heightProperty());
|
||||
//translate it so it sits slightly below the top of the pane.
|
||||
//set the location of the show button to be in the middle of the pane
|
||||
showButton.translateYProperty().bind(displayPane.heightProperty().divide(2).subtract(showButton.heightProperty().divide(2)));
|
||||
|
||||
hidingPane.getHideButton().translateYProperty().setValue(yPos);
|
||||
|
@ -27,177 +27,14 @@ import whistlesAndMoans.AbstractWhistleDataUnit;
|
||||
*/
|
||||
public class DelphinIDTest {
|
||||
|
||||
public static DelphinIDWorkerTest prepDelphinIDModel(String modelPath) {
|
||||
|
||||
//create the delphinID worker.
|
||||
DelphinIDWorkerTest delphinIDWorker = new DelphinIDWorkerTest();
|
||||
|
||||
StandardModelParams params = new StandardModelParams();
|
||||
params.modelPath = modelPath;
|
||||
|
||||
//prepare the model
|
||||
delphinIDWorker.prepModel(params, null);
|
||||
|
||||
return delphinIDWorker;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load whistle contours from a MAT file. ()
|
||||
*
|
||||
* @param filePath - the file path.
|
||||
*
|
||||
* @return a list of whistle contour objects from the mat file.
|
||||
*/
|
||||
public static ArrayList<AbstractWhistleDataUnit> getWhistleContoursMAT(String filePath){
|
||||
|
||||
ArrayList<AbstractWhistleDataUnit> contours = new ArrayList<AbstractWhistleDataUnit>();
|
||||
|
||||
// SegmenterDetectionGroup segmenterDetectionGroup = new SegmenterDetectionGroup(0, 0, 0, 0);
|
||||
|
||||
// Read scalar from nested struct
|
||||
try {
|
||||
Mat5File matFile = Mat5.readFromFile(filePath);
|
||||
Struct whistlesStruct = matFile.getStruct("whistles");
|
||||
|
||||
double fftLen = matFile.getMatrix("fftlen").getDouble(0);
|
||||
double fftHop = matFile.getMatrix("ffthop").getDouble(0);
|
||||
double sampleRate = matFile.getMatrix("samplerate").getDouble(0);
|
||||
|
||||
for (int i=0; i< whistlesStruct.getNumElements(); i++) {
|
||||
DataUnitBaseData basicData = new DataUnitBaseData();
|
||||
|
||||
long timeMillis = ((Matrix)whistlesStruct.get("millis", i)).getLong(0);
|
||||
basicData.setTimeMilliseconds(timeMillis);
|
||||
|
||||
long sampleDuration = ((Matrix)whistlesStruct.get("sampleDuration", i)).getLong(0);
|
||||
basicData.setSampleDuration(sampleDuration);
|
||||
|
||||
basicData.setMillisecondDuration(1000.*(sampleDuration/sampleRate));
|
||||
|
||||
int channelMap = ((Matrix)whistlesStruct.get("channelMap", i)).getInt(0);
|
||||
basicData.setChannelBitmap(channelMap);
|
||||
|
||||
long uid = ((Matrix)whistlesStruct.get("UID", i)).getLong(0);
|
||||
basicData.setUID(uid);
|
||||
|
||||
long startSample = ((Matrix)whistlesStruct.get("startSample", i)).getLong(0);
|
||||
basicData.setStartSample(startSample);
|
||||
|
||||
int nSlices = ((Matrix)whistlesStruct.get("nSlices", i)).getInt(0);
|
||||
|
||||
double[] freq = new double[nSlices];
|
||||
double[] times = new double[nSlices];
|
||||
|
||||
Matrix contourStruct = whistlesStruct.getMatrix("contour", i);
|
||||
for (int j=0; j<nSlices; j++) {
|
||||
freq[j] = contourStruct.getDouble(j)*sampleRate/fftLen;
|
||||
times[j] = j * fftHop /sampleRate;
|
||||
}
|
||||
|
||||
contours.add(new WhistleContourMAT(basicData, freq, times));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return contours;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Segment the detections into groups. Note that segments are overlaps so each whistle may belong to multiple segments.
|
||||
* @param whistles - a list of whistles - not necessarily sorted by time.
|
||||
* @param dataStartMillis - the start time of the data in millis i.e. where the first segment starts.
|
||||
* @param segLen - the segment size in milliseconds.
|
||||
* @param segHop - the segment hop in milliseconds.
|
||||
* @return groups of data units within each segment.
|
||||
*/
|
||||
public static ArrayList<SegmenterDetectionGroup> segmentWhsitleData(ArrayList<AbstractWhistleDataUnit> whistles, long dataStartMillis,
|
||||
double segLen, double segHop){
|
||||
|
||||
ArrayList<SegmenterDetectionGroup> group = new ArrayList<SegmenterDetectionGroup>();
|
||||
|
||||
//find the maximum whistle time
|
||||
long maxTime = Long.MIN_VALUE;
|
||||
long endTime = 0;
|
||||
for (AbstractWhistleDataUnit whislte: whistles) {
|
||||
endTime = (long) (whislte.getTimeMilliseconds()+whislte.getDurationInMilliseconds());
|
||||
if (endTime>maxTime) maxTime=endTime;
|
||||
}
|
||||
|
||||
long segStart = dataStartMillis;
|
||||
long segEnd = (long) (segStart+segLen);
|
||||
|
||||
long whistleStart;
|
||||
long whistleEnd;
|
||||
SegmenterDetectionGroup whistleGroup;
|
||||
while (segStart<endTime){
|
||||
|
||||
whistleGroup = new SegmenterDetectionGroup(segStart, 1, segEnd, segLen);
|
||||
|
||||
for (AbstractWhistleDataUnit whislte: whistles) {
|
||||
whistleStart = whislte.getTimeMilliseconds();
|
||||
whistleEnd = (long) (whislte.getTimeMilliseconds() + whislte.getDurationInMilliseconds());
|
||||
|
||||
if ((whistleStart>=segStart && whistleStart<segEnd) || ((whistleEnd>=segStart && whistleEnd<segEnd))){
|
||||
//some part of the whistle is in the segment.
|
||||
whistleGroup.addSubDetection(whislte);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
group.add(whistleGroup);
|
||||
|
||||
// System.out.println("SegStart: " + (segStart - dataStartMillis));
|
||||
|
||||
segStart = (long) (segStart+segHop);
|
||||
segEnd = (long) (segStart+segLen);
|
||||
}
|
||||
|
||||
return group;
|
||||
|
||||
}
|
||||
|
||||
public static class WhistleContourMAT extends AbstractWhistleDataUnit {
|
||||
|
||||
private double[] freq;
|
||||
private double[] times;
|
||||
|
||||
public WhistleContourMAT(DataUnitBaseData basicData, double[] freq, double[] times) {
|
||||
super(basicData);
|
||||
this.freq=freq;
|
||||
this.times=times;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSliceCount() {
|
||||
return freq.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getTimesInSeconds() {
|
||||
return times;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getFreqsHz() {
|
||||
return freq;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class DelphinIDWorkerTest extends DelphinIDWorker {
|
||||
|
||||
private float[][][] lastModelInput;
|
||||
|
||||
|
||||
public float[][][] dataUnits2ModelInput(ArrayList<? extends PamDataUnit> dataUnits, float sampleRate, int iChan){
|
||||
|
||||
float[][][] data = super.dataUnits2ModelInput(dataUnits, sampleRate, iChan);
|
||||
|
||||
this.lastModelInput = data;
|
||||
@ -237,10 +74,10 @@ public class DelphinIDTest {
|
||||
MatFile matFile = Mat5.newMatFile();
|
||||
|
||||
//get the whislte contours form a .mat file.
|
||||
ArrayList<AbstractWhistleDataUnit> whistleContours = getWhistleContoursMAT(whistleContourPath);
|
||||
ArrayList<AbstractWhistleDataUnit> whistleContours = DelphinIDUtils.getWhistleContoursMAT(whistleContourPath);
|
||||
|
||||
//segment the whistle detections
|
||||
ArrayList<SegmenterDetectionGroup> segments = segmentWhsitleData(whistleContours, (long) (dataStartMillis+(9.565*1000.)),
|
||||
ArrayList<SegmenterDetectionGroup> segments = DelphinIDUtils.segmentWhsitleData(whistleContours, (long) (dataStartMillis+(9.565*1000.)),
|
||||
segLen, segHop);
|
||||
|
||||
for (int i=0; i<segments.size(); i++) {
|
||||
@ -248,7 +85,7 @@ public class DelphinIDTest {
|
||||
}
|
||||
|
||||
//prepare the model - this loads the zip file and loads the correct transforms.
|
||||
DelphinIDWorkerTest model = prepDelphinIDModel(modelPath);
|
||||
DelphinIDWorkerTest model = DelphinIDUtils.prepDelphinIDModel(modelPath);
|
||||
model.setEnableSoftMax(false);
|
||||
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
package rawDeepLearningClassifier.dlClassification.delphinID;
|
||||
|
||||
|
@ -0,0 +1,330 @@
|
||||
package rawDeepLearningClassifier.dlClassification.delphinID;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import PamUtils.FileList;
|
||||
import PamUtils.PamArrayUtils;
|
||||
import PamUtils.TxtFileUtils;
|
||||
import PamguardMVC.DataUnitBaseData;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams;
|
||||
import rawDeepLearningClassifier.dlClassification.delphinID.DelphinIDTest.DelphinIDWorkerTest;
|
||||
import rawDeepLearningClassifier.segmenter.SegmenterDetectionGroup;
|
||||
import us.hebi.matlab.mat.format.Mat5;
|
||||
import us.hebi.matlab.mat.format.Mat5File;
|
||||
import us.hebi.matlab.mat.types.Matrix;
|
||||
import us.hebi.matlab.mat.types.Struct;
|
||||
import whistlesAndMoans.AbstractWhistleDataUnit;
|
||||
|
||||
/**
|
||||
* A bunch of utility functions that a re useful for testing and running
|
||||
* DelphinID models
|
||||
*/
|
||||
public class DelphinIDUtils {
|
||||
|
||||
public static DelphinIDWorkerTest prepDelphinIDModel(String modelPath) {
|
||||
|
||||
//create the delphinID worker.
|
||||
DelphinIDWorkerTest delphinIDWorker = new DelphinIDWorkerTest();
|
||||
|
||||
StandardModelParams params = new StandardModelParams();
|
||||
params.modelPath = modelPath;
|
||||
|
||||
//prepare the model
|
||||
delphinIDWorker.prepModel(params, null);
|
||||
|
||||
return delphinIDWorker;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load whistle contours from a MAT file. ()
|
||||
*
|
||||
* @param filePath - the file path.
|
||||
*
|
||||
* @return a list of whistle contour objects from the mat file.
|
||||
*/
|
||||
public static ArrayList<AbstractWhistleDataUnit> getWhistleContoursMAT(String filePath){
|
||||
|
||||
ArrayList<AbstractWhistleDataUnit> contours = new ArrayList<AbstractWhistleDataUnit>();
|
||||
|
||||
// SegmenterDetectionGroup segmenterDetectionGroup = new SegmenterDetectionGroup(0, 0, 0, 0);
|
||||
|
||||
// Read scalar from nested struct
|
||||
try {
|
||||
Mat5File matFile = Mat5.readFromFile(filePath);
|
||||
|
||||
Struct whistlesStruct = matFile.getStruct("whistles");
|
||||
|
||||
double fftLen = matFile.getMatrix("fftlen").getDouble(0);
|
||||
double fftHop = matFile.getMatrix("ffthop").getDouble(0);
|
||||
double sampleRate = matFile.getMatrix("samplerate").getDouble(0);
|
||||
|
||||
return getWhistleContoursMAT(whistlesStruct, fftLen, fftHop, sampleRate);
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return contours;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load whistle contours from a MATLAB struct
|
||||
|
||||
* @param whistlesStruct - a struct containing a list of whistle contours
|
||||
* @param fftLen- the fft length in samples
|
||||
* @param fftHop - the fft hop in samples.
|
||||
* @param sampleRate - the sample rate in samples per second.
|
||||
* @return a list of whistle contour objects from the struct.
|
||||
*/
|
||||
public static ArrayList<AbstractWhistleDataUnit> getWhistleContoursMAT(Struct whistlesStruct, double fftLen, double fftHop, double sampleRate){
|
||||
|
||||
ArrayList<AbstractWhistleDataUnit> contours = new ArrayList<AbstractWhistleDataUnit>();
|
||||
|
||||
|
||||
for (int i=0; i< whistlesStruct.getNumElements(); i++) {
|
||||
DataUnitBaseData basicData = new DataUnitBaseData();
|
||||
|
||||
long timeMillis = ((Matrix)whistlesStruct.get("millis", i)).getLong(0);
|
||||
basicData.setTimeMilliseconds(timeMillis);
|
||||
|
||||
long sampleDuration = ((Matrix)whistlesStruct.get("sampleDuration", i)).getLong(0);
|
||||
basicData.setSampleDuration(sampleDuration);
|
||||
|
||||
basicData.setMillisecondDuration(1000.*(sampleDuration/sampleRate));
|
||||
|
||||
int channelMap = ((Matrix)whistlesStruct.get("channelMap", i)).getInt(0);
|
||||
basicData.setChannelBitmap(channelMap);
|
||||
|
||||
long uid = ((Matrix)whistlesStruct.get("UID", i)).getLong(0);
|
||||
basicData.setUID(uid);
|
||||
|
||||
long startSample = ((Matrix)whistlesStruct.get("startSample", i)).getLong(0);
|
||||
basicData.setStartSample(startSample);
|
||||
|
||||
int nSlices = ((Matrix)whistlesStruct.get("nSlices", i)).getInt(0);
|
||||
|
||||
double[] freq = new double[nSlices];
|
||||
double[] times = new double[nSlices];
|
||||
|
||||
Matrix contourStruct = whistlesStruct.getMatrix("contour", i);
|
||||
for (int j=0; j<nSlices; j++) {
|
||||
freq[j] = contourStruct.getDouble(j)*sampleRate/fftLen;
|
||||
times[j] = j * fftHop /sampleRate;
|
||||
}
|
||||
|
||||
contours.add(new WhistleContourMAT(basicData, freq, times));
|
||||
}
|
||||
|
||||
return contours;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Segment the detections into groups. Note that segments are overlaps so each whistle may belong to multiple segments.
|
||||
* @param whistles - a list of whistles - not necessarily sorted by time.
|
||||
* @param dataStartMillis - the start time of the data in millis i.e. where the first segment starts.
|
||||
* @param segLen - the segment size in milliseconds.
|
||||
* @param segHop - the segment hop in milliseconds.
|
||||
* @return groups of data units within each segment.
|
||||
*/
|
||||
public static ArrayList<SegmenterDetectionGroup> segmentWhsitleData(ArrayList<AbstractWhistleDataUnit> whistles, long dataStartMillis,
|
||||
double segLen, double segHop){
|
||||
|
||||
ArrayList<SegmenterDetectionGroup> group = new ArrayList<SegmenterDetectionGroup>();
|
||||
|
||||
//find the maximum whistle time
|
||||
long maxTime = Long.MIN_VALUE;
|
||||
long endTime = 0;
|
||||
for (AbstractWhistleDataUnit whislte: whistles) {
|
||||
endTime = (long) (whislte.getTimeMilliseconds()+whislte.getDurationInMilliseconds());
|
||||
if (endTime>maxTime) maxTime=endTime;
|
||||
}
|
||||
|
||||
long segStart = dataStartMillis;
|
||||
long segEnd = (long) (segStart+segLen);
|
||||
|
||||
long whistleStart;
|
||||
long whistleEnd;
|
||||
SegmenterDetectionGroup whistleGroup;
|
||||
while (segStart<endTime){
|
||||
|
||||
whistleGroup = new SegmenterDetectionGroup(segStart, 1, segEnd, segLen);
|
||||
|
||||
for (AbstractWhistleDataUnit whislte: whistles) {
|
||||
whistleStart = whislte.getTimeMilliseconds();
|
||||
whistleEnd = (long) (whislte.getTimeMilliseconds() + whislte.getDurationInMilliseconds());
|
||||
|
||||
if ((whistleStart>=segStart && whistleStart<segEnd) || ((whistleEnd>=segStart && whistleEnd<segEnd))){
|
||||
//some part of the whistle is in the segment.
|
||||
whistleGroup.addSubDetection(whislte);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
group.add(whistleGroup);
|
||||
|
||||
// System.out.println("SegStart: " + (segStart - dataStartMillis));
|
||||
|
||||
segStart = (long) (segStart+segHop);
|
||||
segEnd = (long) (segStart+segLen);
|
||||
}
|
||||
|
||||
return group;
|
||||
|
||||
}
|
||||
|
||||
public static class WhistleContourMAT extends AbstractWhistleDataUnit {
|
||||
|
||||
private double[] freq;
|
||||
private double[] times;
|
||||
|
||||
public WhistleContourMAT(DataUnitBaseData basicData, double[] freq, double[] times) {
|
||||
super(basicData);
|
||||
this.freq=freq;
|
||||
this.times=times;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSliceCount() {
|
||||
return freq.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getTimesInSeconds() {
|
||||
return times;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getFreqsHz() {
|
||||
return freq;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void generateImages(Struct whistlesStruct, String outName, DelphinIDWorker worker, double fftLen, double fftHop, double sampleRate) {
|
||||
|
||||
double segLen = 4000.;
|
||||
double segHop = 1000.0;
|
||||
|
||||
// ArrayList<ArrayList<Double>> contourData = TxtFileUtils.importCSVData(csvFile);
|
||||
ArrayList<AbstractWhistleDataUnit> whistles = getWhistleContoursMAT(whistlesStruct, fftLen, fftHop, sampleRate);
|
||||
|
||||
//segment the whistle detections
|
||||
ArrayList<SegmenterDetectionGroup> segments = DelphinIDUtils.segmentWhsitleData(whistles, whistles.get(0).getTimeMilliseconds(), segLen, segHop);
|
||||
|
||||
float[][][] images = worker.dataUnits2ModelInput(segments, (float) sampleRate, 0);
|
||||
|
||||
float[][] image;
|
||||
BufferedImage bfImage;
|
||||
for (int k=0; k<images.length; k++) {
|
||||
image = images[k];
|
||||
|
||||
bfImage = new BufferedImage(image.length, image[0].length, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// System.out.println("Max of image: " + PamArrayUtils.minmax(image)[1]);
|
||||
|
||||
for(int i = 0; i < image.length; i++) {
|
||||
for(int j = 0; j < image[0].length; j++) {
|
||||
Color myRGB = new Color(image[i][j], image[i][j], image[i][j]);
|
||||
int rgb = myRGB.getRGB();
|
||||
bfImage.setRGB(i, j, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
//now save the image
|
||||
String outputPath = outName + "_" + k + ".png";
|
||||
|
||||
File outputfile = new File(outputPath);
|
||||
|
||||
try {
|
||||
ImageIO.write(bfImage, "png", outputfile);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
//the whsitle contours as csv files.
|
||||
String whistlefolder = "/Users/au671271/Library/CloudStorage/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/training/WMD";
|
||||
|
||||
//the image folder to save to.
|
||||
String imageFolder = "/Users/au671271/Library/CloudStorage/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/training/WMD_Images";
|
||||
|
||||
//the path to the model
|
||||
String modelPath = "/Users/au671271/Library/CloudStorage/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/testencounter415/whistle_model_2/whistle_4s_415.zip";
|
||||
|
||||
//prepare the model - this loads the zip file and loads the correct transforms.
|
||||
DelphinIDWorkerTest model;
|
||||
|
||||
model = DelphinIDUtils.prepDelphinIDModel(modelPath);
|
||||
model.setEnableSoftMax(false);
|
||||
|
||||
FileList filelist = new FileList();
|
||||
|
||||
File folder = new File(whistlefolder);
|
||||
File[] listOfFiles = folder.listFiles();
|
||||
if(listOfFiles != null) {
|
||||
for (int i = 0; i < listOfFiles.length; i++) {
|
||||
if (listOfFiles[i].isDirectory()) {
|
||||
//get a list of csv files
|
||||
// ArrayList<File> csvFiles = filelist.getFileList(listOfFiles[i].getAbsolutePath(), ".mat" , true);
|
||||
|
||||
System.out.println("Directory " + listOfFiles[i].getName());
|
||||
|
||||
File outFolder = new File(imageFolder + File.separator + listOfFiles[i].getName());
|
||||
outFolder.mkdir();//make the out folder directory
|
||||
|
||||
try {
|
||||
|
||||
File file = new File(listOfFiles[i].getPath() + File.separator + "whistles.mat");
|
||||
Mat5File matFile = Mat5.readFromFile(file);
|
||||
|
||||
Struct whistlesStruct = matFile.getStruct("whistles");
|
||||
|
||||
double fftLen = matFile.getMatrix("fftlen").getDouble(0);
|
||||
double fftHop = matFile.getMatrix("ffthop").getDouble(0);
|
||||
double sampleRate = matFile.getMatrix("samplerate").getDouble(0);
|
||||
|
||||
List<String> fieldNames = whistlesStruct.getFieldNames();
|
||||
|
||||
Struct whistecontours;
|
||||
for (String name: fieldNames) {
|
||||
System.out.println("Generating images for recording " + name + " from " + listOfFiles[i].getName());
|
||||
if (!name.equals("fftlen") && !name.equals("ffthop") && !name.equals("samplerate")) {
|
||||
whistecontours = whistlesStruct.get(name);
|
||||
generateImages( whistecontours, (outFolder + File.separator + name) , model, fftLen, fftHop, sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -95,9 +95,7 @@ public class DelphinIDWorker extends ArchiveModelWorker {
|
||||
return whistle2ImageParmas;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//something has gone wrong if we get here.
|
||||
return null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user