diff --git a/.classpath b/.classpath index e121c1d6..68536b87 100644 --- a/.classpath +++ b/.classpath @@ -8,7 +8,6 @@ - diff --git a/src/PamUtils/PamArrayUtils.java b/src/PamUtils/PamArrayUtils.java index d18ae641..e6467abd 100644 --- a/src/PamUtils/PamArrayUtils.java +++ b/src/PamUtils/PamArrayUtils.java @@ -22,19 +22,19 @@ public class PamArrayUtils { /** * Calculate the mean of one dimension within a list of points. e.g. the points might be a list of [x y z] co-ordinates in * which case the dim=0 would return the mean of all x points. - * @param array - a list of points + * @param successJump - a list of points * @param InitialtoIgnorePercentage: ignore the first percentage of results * @param dim - the dimension of the point to calculate the average for * @return the mean of one dimension of the list of the points. */ - public static double mean(ArrayList array, double InitialtoIgnorePercentage, int dim){ + public static double mean(ArrayList successJump, double InitialtoIgnorePercentage, int dim){ double meanTotal=0; int n=0; - int forStart=(int) Math.round((InitialtoIgnorePercentage)*array.size()); + int forStart=(int) Math.round((InitialtoIgnorePercentage)*successJump.size()); - for (int i=forStart; i array, double initialtoIgnorePercentage, int dim){ + public static double std(ArrayList successJump, double initialtoIgnorePercentage, int dim){ double std=0.0; int n=0; - int forStart=(int) Math.round((initialtoIgnorePercentage)*array.size()); + int forStart=(int) Math.round((initialtoIgnorePercentage)*successJump.size()); - double meanTotal= mean(array, initialtoIgnorePercentage, dim); + double meanTotal= mean(successJump, initialtoIgnorePercentage, dim); //calculate standard deviation - for (int k=forStart;kmax) { + index = count; + max=cur; + } + count++; + } + + + return index; + } + + /** + * Get the minimum index of an array + * @param arr - the array to find the position of the maximum value. + * m value of. + * @return the index of the minimum value + */ + public static int minPos(double[] arr) { + double max = Double.POSITIVE_INFINITY; + int index = -1; + + int count = 0; + for(double cur: arr) { + if (cur= 0; i--) { PamDataUnit subDet = superDet.getSubDetection(i); - if (subDet.getChannelBitmap() == clickDetection.getChannelBitmap()) { + if (subDet!=null && subDet.getChannelBitmap() == clickDetection.getChannelBitmap()) { double ici = (double) (clickDetection.getTimeMilliseconds() - subDet.getTimeMilliseconds())/1000.; clickDetection.setTempICI(ici); break; diff --git a/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java index 59123830..e2cf0f39 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java @@ -1,13 +1,18 @@ package clickDetector.layoutFX.clickClassifiers; import pamViewFX.fxNodes.PamBorderPane; +import pamViewFX.fxNodes.PamSymbolFX; import pamViewFX.fxNodes.flipPane.PamFlipPane; import pamViewFX.fxNodes.table.TableSettingsPane; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import javafx.geometry.Insets; +import javafx.geometry.Point2D; import javafx.scene.Node; +import javafx.scene.canvas.Canvas; import javafx.scene.control.Button; import javafx.scene.control.Dialog; +import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.cell.CheckBoxTableCell; import clickDetector.BasicClickIdParameters; @@ -15,6 +20,7 @@ import clickDetector.ClickControl; import clickDetector.ClickTypeParams; import clickDetector.ClickClassifiers.ClickIdentifier; import clickDetector.ClickClassifiers.basic.BasicClickIdentifier; +import clickDetector.ClickClassifiers.basicSweep.*; /** * Pane for the basic click classifier. @@ -23,33 +29,33 @@ import clickDetector.ClickClassifiers.basic.BasicClickIdentifier; * */ public class BasicIdentifierPaneFX implements ClassifyPaneFX { - + /** * Reference to the basicClickIdentifier. */ private ClickIdentifier basicClickIdentifier; - + /** * Reference to the click control. */ protected ClickControl clickControl; - + /** * Pane which holds table data. */ - private TableSettingsPane settingsPane; - -// /** -// * Hiding pane which slides out to allow users to change click type settings. -// */ -// protected HidingPane hidingPane; - + protected TableSettingsPane clickTypesTable; + + // /** + // * Hiding pane which slides out to allow users to change click type settings. + // */ + // protected HidingPane hidingPane; + /** * Holds click classifier controls inside hiding pane. */ protected PamBorderPane clickTypeHolder; - + /** * A list of click classifiers currently shown in the table.It Would have been much easier to have this in params * but didn't want to add any FX related as these should be GUI independent classes. @@ -60,19 +66,19 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { * Holds the table. */ protected PamBorderPane mainHolderPane; - -// /** -// * The width of the hiding pane -// */ -// private double hidingPaneWidth=900; + + // /** + // * The width of the hiding pane + // */ + // private double hidingPaneWidth=900; /** * Cloned copy of BasicClickIdParameters. */ private BasicClickIdParameters basicClickIdParameters; - + private PamBorderPane mainPane; - + private PamFlipPane flipPane; /** @@ -85,7 +91,7 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { this.basicClickIdentifier= basicClickIdentifier; this.clickControl=clickControl; mainPane= new PamBorderPane(); - + flipPane = new PamFlipPane(); flipPane.getFrontPane().setCenter(createSettingsPane()); flipPane.getBackPane().setCenter(clickTypeHolder); @@ -93,35 +99,36 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { mainPane.setCenter(flipPane); } - - - + + + /** * Create the controls for the basic click identifier pane. * @return node with all controls for basic click classifier. */ protected Node createSettingsPane(){ - + mainHolderPane=new PamBorderPane(); - mainHolderPane.setCenter(settingsPane=new ClickClassifierTable(clickClassifiers)); - + mainHolderPane.setPadding(new Insets(5,5,5,5)); + mainHolderPane.setCenter(clickTypesTable=new ClickClassifierTable(clickClassifiers)); + clickTypeHolder=new PamBorderPane(); //clickTypeHolder.setPrefWidth(hidingPaneWidth); - + return mainHolderPane; - + } - -// /** -// * Added purely so can be override and hiding pane set in different location if required -// */ -// public void createHidingPane(){ -// hidingPane=new HidingPane(Side.RIGHT, clickTypeHolder, mainPane, false); -// //hidingPane.showHidePane(false); -// mainHolderPane.setRight(hidingPane); -// hidingPane.showHidePane(false); -// } - + + // /** + // * Added purely so can be override and hiding pane set in different location if required + // */ + // public void createHidingPane(){ + // hidingPane=new HidingPane(Side.RIGHT, clickTypeHolder, mainPane, false); + // //hidingPane.showHidePane(false); + // mainHolderPane.setRight(hidingPane); + // hidingPane.showHidePane(false); + // } + @Override @@ -133,7 +140,7 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { public void setParams() { basicClickIdParameters = ((BasicClickIdentifier) basicClickIdentifier).getIdParameters().clone(); //change the observable list. - + } @Override @@ -151,9 +158,9 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { @Override public void setActive(boolean b) { // TODO Auto-generated method stub - + } - + /** * Class which extends TableSettingsPane and creates a sliding pane instead of a dialog when an item is added. * @author Jamie Macaulay @@ -164,33 +171,43 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { public ClickClassifierTable(ObservableList data) { super(data); //need to set up all the rows. - - TableColumn name = new TableColumn("Name"); - name.setCellValueFactory(cellData -> cellData.getValue().name); - name.setEditable(true); - + + TableColumn icon = new TableColumn("Name"); + icon.setCellValueFactory(cellData -> cellData.getValue().name); + icon.setEditable(false); + + icon.setCellFactory((tableColumn) -> { + TableCell tableCell = new ClickTypeNameCell(); + return tableCell; + }); + + // TableColumn name = new TableColumn("Name"); + // name.setCellValueFactory(cellData -> cellData.getValue().name); + // name.setEditable(true); + + TableColumn code = new TableColumn("Species Code"); code.setCellValueFactory(cellData -> cellData.getValue().code); - + TableColumn checkCol = new TableColumn<>("Enable"); checkCol.setCellValueFactory( cellData -> cellData.getValue().enableClassifier); checkCol.setCellFactory(CheckBoxTableCell.forTableColumn(checkCol)); checkCol.setEditable(true); checkCol.setMaxWidth( 100 ); checkCol.setMinWidth( 100 ); - - + + TableColumn discard = new TableColumn<>("Discard"); discard.setCellValueFactory( cellData -> cellData.getValue().discardClassifier); discard.setCellFactory(CheckBoxTableCell.forTableColumn(checkCol)); discard.setEditable(true); discard.setMaxWidth( 100 ); discard.setMinWidth( 100 ); - + getTableView().setEditable(true); - - getTableView().getColumns().addAll(checkCol, name, code, discard); + + getTableView().getColumns().addAll(checkCol, icon, code, discard); } @@ -206,33 +223,33 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { showFlipPane(true); return null; } - + @Override public void editData(ClickTypeProperty data){ setClassifierPane(data); showFlipPane(true); } - + @Override public void createNewData(){ //create a new classifier. clickClassifiers.add(createClickTypeProperty()); } - + } - -// /** -// * Show the hiding pane which contains classifier settings -// * NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016 -// * @param show - true to show pane. -// */ -// public void showHidingPane(boolean show){ -// if (hidingPane==null){ -// this.createHidingPane(); -// } -// hidingPane.showHidePane(true); -// } - + + // /** + // * Show the hiding pane which contains classifier settings + // * NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016 + // * @param show - true to show pane. + // */ + // public void showHidingPane(boolean show){ + // if (hidingPane==null){ + // this.createHidingPane(); + // } + // hidingPane.showHidePane(true); + // } + /** * Show the flip pane. * NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016 @@ -247,33 +264,34 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { flipPane.flipToFront(); } } - + /** * Create click classifier. */ public ClickTypeProperty createClickTypeProperty(){ return new ClickTypeProperty(new ClickTypeParams(clickClassifiers.size())); } - + /** * Set classifier pane within hiding pane. * @param clickTypeProperty */ public void setClassifierPane(ClickTypeProperty clickTypeProperty){ - - + ClickTypePaneFX clickTypePane=new ClickTypePaneFX(); clickTypePane.setParams(clickTypeProperty); - + clickTypeHolder.setCenter(clickTypePane.getContentNode()); - + //now need to make sure on closing the pane that settings are saved. Need to //remove the old click type from the list and add new one in the same position. getFlipPaneCloseButton().setOnAction((action)->{ - //System.out.println("CLOSE FLIP PANE"); showFlipPane(false); //this should update the click type property in the observable list thus changing the table clickTypePane.getParams(clickTypeProperty); + + //need to refresh table to show symbol. + clickTypesTable.getTableView().refresh(); }); } @@ -285,16 +303,16 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { return flipPane.getBackButton(); } -// /** -// * Get the hiding pane which holds settings for different click types. -// * @return the HidingPane for click classifiers. -// */ -// public HidingPane getClickTypeHidingPane() { -// if (hidingPane==null) { -// this.createHidingPane(); -// } -// return hidingPane; -// } + // /** + // * Get the hiding pane which holds settings for different click types. + // * @return the HidingPane for click classifiers. + // */ + // public HidingPane getClickTypeHidingPane() { + // if (hidingPane==null) { + // this.createHidingPane(); + // } + // return hidingPane; + // } /** * Get the pane which holds the ClickTypePaneFX. @@ -303,15 +321,15 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { public PamBorderPane getClickTypeHolder() { return clickTypeHolder; }; - + /** * Get the table which holds a list of classifier * @return table which holds a list of classifiers */ public TableSettingsPane getTablePane() { - return this.settingsPane; + return this.clickTypesTable; }; - + /** * Get list of click classifiers * @return list of click classifiers @@ -329,4 +347,48 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { return flipPane; } + + /** + * Shows a name alongside a graphic showing the current symbol. + * @author Jamie Macaulay. + * + */ + private class ClickTypeNameCell extends TableCell { + + /** + * Symbol is drawn on the canvas + */ + Canvas canvas; + + public static final double SYMBOL_SIZE = 20; + + public ClickTypeNameCell() { + super(); + canvas = new Canvas(SYMBOL_SIZE, SYMBOL_SIZE); + } + + + @Override + protected void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + + this.setText(item); + + this.setGraphic(null); + + if (this.getTableRow()!=null && this.getTableRow().getItem()!=null) { + + SweepClassifierSet clickProperty = (SweepClassifierSet) this.getTableRow().getItem().getClickType(); + + if (clickProperty.symbol!=null) { + canvas.getGraphicsContext2D().clearRect(0, 0, SYMBOL_SIZE, SYMBOL_SIZE); + PamSymbolFX pamSymbolFX = new PamSymbolFX(clickProperty.symbol); + pamSymbolFX.draw(canvas.getGraphicsContext2D(), new Point2D(SYMBOL_SIZE/2,SYMBOL_SIZE/2), SYMBOL_SIZE, SYMBOL_SIZE); + this.setGraphic(canvas); + } + } + + } + }; + } diff --git a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java index e9a0979b..ba4fbf5e 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java @@ -1,10 +1,16 @@ package clickDetector.layoutFX.clickClassifiers; + import clickDetector.ClickControl; import clickDetector.ClickClassifiers.basicSweep.SweepClassifier; import clickDetector.ClickClassifiers.basicSweep.SweepClassifierParameters; import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet; +import javafx.scene.text.FontPosture; +import javafx.scene.text.FontWeight; +import javafx.scene.layout.Region; +import javafx.scene.text.Font; +import javafx.geometry.Insets; /** * Slightly different pane for the sweep classifier. @@ -38,12 +44,17 @@ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX { @Override public void setClassifierPane(ClickTypeProperty clickTypeProperty){ SweepClassifierSetPaneFX sweepPane=new SweepClassifierSetPaneFX(sweepClickClassifier); - + + //set padding - want the flip pane not to have padding so back button reaches edge of node. + ((Region) sweepPane.getContentNode()).setPadding(new Insets(5,5,5,5)); //make it so the title of the pane is the same as the name as the classifier getFlipPane().getAdvLabel().textProperty().unbind(); - getFlipPane().getAdvLabel().textProperty().bind( sweepPane.getNameTextProperty()); + getFlipPane().getAdvLabel().textProperty().bind(sweepPane.getNameTextProperty()); + // removed DG 2023 12 14 since not everything was in this merge that was required Needs to be put back. +// getFlipPane().getPreAdvLabel().graphicProperty().bind(sweepPane.getNameGraphicProperty()); + sweepPane.classifierItemRow = sweepClickClassifier.getSweepClassifierParams().getSetRow((SweepClassifierSet) clickTypeProperty.getClickType()); sweepPane.setParams(clickTypeProperty); @@ -54,6 +65,8 @@ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX { getFlipPaneCloseButton().setOnAction((action)->{ showFlipPane(false); sweepPane.getParams(clickTypeProperty); + //need to refresh table to show symbol. + clickTypesTable.getTableView().refresh(); }); } diff --git a/src/matchedTemplateClassifer/ImportTemplateCSV.java b/src/matchedTemplateClassifer/ImportTemplateCSV.java index 0713f026..69b1063e 100644 --- a/src/matchedTemplateClassifer/ImportTemplateCSV.java +++ b/src/matchedTemplateClassifer/ImportTemplateCSV.java @@ -2,7 +2,9 @@ package matchedTemplateClassifer ; import java.io.File; +import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Collection; import PamUtils.PamArrayUtils; import PamUtils.TxtFileUtils; @@ -44,16 +46,21 @@ public class ImportTemplateCSV implements TemplateImport { //System.out.println("i: " + i + " : " + data.get(0).get(i)); waveform[i]=data.get(0).get(i); } +// System.out.println("String sR = " + data.get(1).get(0)); + + + //used big decimal here because String.,floatValue did not handle numbers like 3.85e05 + float sR = new BigDecimal(data.get(1).get(0)).floatValue(); - float sR=data.get(1).get(0).floatValue(); +// float sR=data.get(1).get(0).floatValue(); //System.out.println("imported waveform"); //PamArrayUtils.printArrayRaw(waveform); //now create waveform -// System.out.println("Create a waveform with " + waveform.length + " samples with a sample rate of " -// + sR + " Hz"); + System.out.println("Import a waveform with " + waveform.length + " samples with a sample rate of " + + sR + " Hz "); MatchTemplate matchedTemplate = new MatchTemplate(filePath.getName(), waveform, sR); //TODO return matchedTemplate; diff --git a/src/matchedTemplateClassifer/MTClassifier.java b/src/matchedTemplateClassifer/MTClassifier.java index 377fc135..9065daac 100644 --- a/src/matchedTemplateClassifer/MTClassifier.java +++ b/src/matchedTemplateClassifer/MTClassifier.java @@ -130,7 +130,7 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters if (fft==null) fft=new FastFFT(); - //System.out.println("interpWaveform: " + waveformMatch.waveform.length + " sR " + waveformMatch.sR); +// System.out.println("interpWaveform: " + waveformMatch.waveform.length + " sR " + waveformMatch.sR); //re-sample the waveform if the sample rate is different this.interpWaveformMatch=interpWaveform(this.waveformMatch, sR); @@ -146,7 +146,12 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters // System.out.println("MatchNorm: MATCH"); // MTClassifierTest.normalizeTest(interpWaveformMatch); - waveformMatchFFT = fft.rfft(interpWaveformMatch, length); + /** + * There is an issue here because, if we have a long template waveform, then it + * will become truncated and the actual waveform may be missed. This means we + * have to use the peak of the template + */ + waveformMatchFFT = calcTemplateFFT(interpWaveformMatch, length); //need to calculate the complex conjugate - note that originally I was flipping the array but this means //the max value does not equal one with identical waveforms...doh. @@ -158,6 +163,42 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters return waveformMatchFFT; } + + /** + * Calculate the FFT of an interpolate match template. + * @param interpTemplateWaveform - the waveform interpolated to the correct sample rate. + * @param length - the length of the FFT. + * @return the FFT of the waveform as a complex array. + */ + private ComplexArray calcTemplateFFT(double[] interpTemplateWaveform, int length) { + + ComplexArray fftTemplate; + /** + * There is an issue here because, if we have a long template waveform, then it + * will become truncated and the actual waveform may be missed. This means we + * have to use the peak of the template + */ + if (interpTemplateWaveform.length>length) { + //If the template is long then need to find the peak, otherwise we will end up cross correlating with noise at the + //start of the template. + //because this is a template and not a random click we don't need to be so clever with how we find peaks. Find + //the maximum and use around that. + int pos = PamArrayUtils.maxPos(interpTemplateWaveform); + + int startind = Math.max(0, pos-length/2); + int endind = startind+length-1; + + double[] peakTemplate = ArrayUtils.subarray(interpTemplateWaveform, startind, endind); + fftTemplate = fft.rfft(peakTemplate, length); + } + else { + //template waveform is padded by fft function + fftTemplate = fft.rfft(interpTemplateWaveform, length); + } + + return fftTemplate; + } + /** @@ -182,13 +223,17 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters // this.inteprWaveformReject=PamArrayUtils.divide(inteprWaveformReject, PamArrayUtils.max(inteprWaveformReject)); this.inteprWaveformReject = normaliseWaveform(inteprWaveformReject, this.normalisation); - // System.out.println("MatchNorm: REJECT "); // MTClassifierTest.normalizeTest(inteprWaveformReject); // MTClassifierTest.printWaveform(inteprWaveformReject); - //System.out.println("waveformReject: " +inteprWaveformReject.length + " fftLength: " + getFFTLength(sR)); - waveformRejectFFT = fft.rfft(inteprWaveformReject, length); + /** + * There is an issue here because, if we have a long template waveform, then it + * will become truncated and the actual waveform may be missed. This means we + * have to use the peak of the template + */ + waveformRejectFFT = calcTemplateFFT(inteprWaveformReject, length); + //need to calculate the complex conjugate - note that originally I was flipping the array but this means //the max value does not equal one with identical waveforms...doh. @@ -294,7 +339,7 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters ComplexArray matchTemplate = getWaveformMatchFFT(sR, matchResult.length()); - //System.out.println("Match template length: " + matchTemplate.length() + "Click : " + click.length()); +// System.out.println("Match template length: " + matchTemplate.length() + "Click : " + click.length()); for (int i=0; isR) { + if (waveformMatch.sRsR){ + //decimate // //TODO - make a better decimator? // double[] interpWaveformMatch=reSampleWaveform(waveformMatch.waveform, waveformMatch.sR, sR); // return interpWaveformMatch; @@ -495,11 +542,9 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters return wavInterpolator.decimate(waveformMatch.waveform, waveformMatch.sR, (float) sR); } else { - //nothing needed/ + //nothing needed return waveformMatch.waveform; - } - - + } } @@ -530,7 +575,8 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters // // TODO Auto-generated method stub // return PamInterp.interpLinear(x, waveform, xi); - return PamInterp.interpWaveform(waveform, 1/binSize); +// System.out.println("Interp waveform: " + binSize); + return PamInterp.interpWaveform(waveform, 1./binSize); } diff --git a/src/matchedTemplateClassifer/MTProcess.java b/src/matchedTemplateClassifer/MTProcess.java index 32c46040..92e86a2f 100644 --- a/src/matchedTemplateClassifer/MTProcess.java +++ b/src/matchedTemplateClassifer/MTProcess.java @@ -5,6 +5,7 @@ import java.util.Arrays; import PamController.PamController; import PamDetection.RawDataUnit; +import PamUtils.PamArrayUtils; import PamUtils.complex.ComplexArray; import PamView.symbol.PamSymbolManager; import PamguardMVC.PamDataBlock; @@ -288,6 +289,7 @@ public class MTProcess extends PamInstantProcess { @SuppressWarnings("unused") private double[] getWaveData(RawDataHolder clickDetection, int i) { double[] waveform; + if (this.getMTParams().peakSearch) { waveform = createRestrictedLenghtWave(clickDetection, i, lengthData[i], this.getMTParams().restrictedBins); @@ -377,7 +379,14 @@ public class MTProcess extends PamInstantProcess { */ private double[] createRestrictedLenghtWave(RawDataHolder click, int chan, int[] lengthPoints, int restrictedBins) { - return createRestrictedLenghtWave(click, chan, lengthPoints, restrictedBins, getWindow(restrictedBins)); +// System.out.println("Create restricted length wave: " + lengthPoints[0] + " to " + lengthPoints[1]); +// System.out.println("Max before restrict: " + PamArrayUtils.max(click.getWaveData()[chan])); + + double[] wave = createRestrictedLenghtWave(click, chan, lengthPoints, restrictedBins, getWindow(restrictedBins)); + +// System.out.println("Max after restrict: " + PamArrayUtils.max(click.getWaveData()[chan])); + + return wave; } @@ -412,7 +421,7 @@ public class MTProcess extends PamInstantProcess { ArrayList results = new ArrayList(); - //System.out.println("Click waveform max: " + PamArrayUtils.max(clickWaveform) + " sample rate: " + sR); + System.out.println("Click waveform max: " + PamArrayUtils.max(clickWaveform) + " sample rate: " + sR); //normalisation and picking peak has already been performed diff --git a/src/matchedTemplateClassifer/layoutFX/MTSettingsPane.java b/src/matchedTemplateClassifer/layoutFX/MTSettingsPane.java index 2ca0748e..c9c545f6 100644 --- a/src/matchedTemplateClassifer/layoutFX/MTSettingsPane.java +++ b/src/matchedTemplateClassifer/layoutFX/MTSettingsPane.java @@ -328,7 +328,7 @@ public class MTSettingsPane extends SettingsPane { private Node createClassifierPane(){ //with just one classifier. - pamTabPane = new PamTabPane(); + pamTabPane = new PamTabPane(); pamTabPane.setAddTabButton(true); // pamTabPane.getAddTabButton().setGraphic(PamGlyphDude.createPamGlyph(MaterialIcon.ADD, PamGuiManagerFX.iconSize)); pamTabPane.getAddTabButton().setGraphic(PamGlyphDude.createPamIcon("mdi2p-plus", PamGuiManagerFX.iconSize)); diff --git a/src/matchedTemplateClassifer/offline/MTClassifierOfflineTask.java b/src/matchedTemplateClassifer/offline/MTClassifierOfflineTask.java index 99b9ca68..f2544265 100644 --- a/src/matchedTemplateClassifer/offline/MTClassifierOfflineTask.java +++ b/src/matchedTemplateClassifer/offline/MTClassifierOfflineTask.java @@ -40,19 +40,31 @@ public class MTClassifierOfflineTask extends OfflineTask> { @Override public boolean processDataUnit(PamDataUnit dataUnit) { - count++; - mtClassifierControl.getMTProcess().newClickData(dataUnit); + try { +// System.out.println("MT new data unit: " + dataUnit); + + + count++; + mtClassifierControl.getMTProcess().newClickData(dataUnit); + + //since an annotation has been added might need to do this so that the data unit is actually saved. + DataUnitFileInformation fileInfo = dataUnit.getDataUnitFileInformation(); + +// System.out.println("file info: " + fileInfo); + if (fileInfo != null) { + fileInfo.setNeedsUpdate(true); + } + dataUnit.updateDataUnit(System.currentTimeMillis()); + + + return true; - //since an annotation has been added might need to do this so that the data unit is actually saved. - DataUnitFileInformation fileInfo = dataUnit.getDataUnitFileInformation(); - - //System.out.println("file info: " + fileInfo); - if (fileInfo != null) { - fileInfo.setNeedsUpdate(true); } - dataUnit.updateDataUnit(System.currentTimeMillis()); - - return true; + catch (Exception e) { + e.printStackTrace(); + } + return false; + } diff --git a/src/pamViewFX/fxNodes/PamTabPane.java b/src/pamViewFX/fxNodes/PamTabPane.java index 835b5699..9116ed82 100644 --- a/src/pamViewFX/fxNodes/PamTabPane.java +++ b/src/pamViewFX/fxNodes/PamTabPane.java @@ -96,10 +96,12 @@ public class PamTabPane extends TabPane { } /** + * TODO - the button is removed and then added again it does not seem to appear.... * Set whether a button shows to add tabs to the TabPane * @param addTabButton - true to show a button next to the last tab which allows new tabs to be added. */ public void setAddTabButton(boolean addTabButton) { + if (this.addTabButton==addTabButton) return; this.addTabButton = addTabButton; } diff --git a/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java b/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java index 1f0a4ca8..c5a12aaf 100644 --- a/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java +++ b/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java @@ -1,17 +1,26 @@ package pamViewFX.fxNodes.flipPane; -import javafx.geometry.Insets; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.geometry.Orientation; import javafx.geometry.Pos; +import javafx.scene.Node; import javafx.scene.control.Label; +import javafx.scene.control.Labeled; +import javafx.scene.control.TextField; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.paint.Color; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; import pamViewFX.PamGuiManagerFX; import pamViewFX.fxGlyphs.PamGlyphDude; import pamViewFX.fxNodes.PamBorderPane; import pamViewFX.fxNodes.PamButton; import pamViewFX.fxNodes.PamHBox; +import pamViewFX.fxNodes.utilsFX.TextUtilsFX; /** * Flip pane which has is supposed to be used for advanced settings. The front @@ -32,15 +41,34 @@ public class PamFlipPane extends FlipPane { private PamBorderPane frontPane; - private Label advLabel; private PamButton backButton; + /** + * Text field in the title of the advanced pane. This can be used to change settings. + */ + private TextField advLabel; + + /** + * Label which sits before the text field in the advanced settings pane title + */ + private Label preLabel; + + /** + * Label after the the text field in the advanced pane label - this can be set to say "settings" for example with the text field + * then editable to change the name of a parameter. + */ + private Label postLabel; + public PamFlipPane() { super(); this.advPane = createAdvSettingsPane(); this.getFront().getChildren().add(frontPane = new PamBorderPane()); + +// this.getFront().setStyle("-fx-background-color: grey;"); +// this.getBack().setStyle("-fx-background-color: grey;"); + this.getBack().getChildren().add(advPane); this.setFlipTime(FLIP_TIME); @@ -77,6 +105,23 @@ public class PamFlipPane extends FlipPane { public PamBorderPane getAdvPane() { return advPane; } + + + /** + * Set the advanced pane content. + * @param - the content to set. + */ + public void setAdvPaneContent(Node content) { + advPane.setCenter(content); + } + + /** + * Set the front pane content. + * @param - the content to set. + */ + public void setFrontContent(Node content) { + frontPane.setCenter(content); + } /** @@ -86,29 +131,70 @@ public class PamFlipPane extends FlipPane { backButton = new PamButton(); backButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize)); +// backButton.setStyle("-fx-background-color: -color-base-6"); + //backButton.setStyle("-fx-padding: 0,0,0,0"); backButton.setOnAction((action)->{ // System.out.println("FLIP BACK TO FRONT"); this.flipToFront(); }); + //make the back button blue so users can easily see the button. + backButton.setStyle("-fx-background-radius: 0 5 5 0; -fx-border-radius: 0 5 5 0; -fx-background-color: -color-accent-6"); + //backButton.setPrefWidth(150); - PamBorderPane advPane = new PamBorderPane(); - advPane.setPadding(new Insets(5,5,5,5)); + //advPane.setPadding(new Insets(5,5,5,5)); + + // holds the title of the advanced pane. This consists of a label for a graphic, + // an editable text field and a label after the editable settings field + PamHBox titleHolder = new PamHBox(); + titleHolder.getChildren().addAll(preLabel = new Label(), advLabel = new TextField("Adv. "), postLabel = new Label("Settings")); + preLabel.setId("label-title2"); + postLabel.setId("label-title2"); + titleHolder.setAlignment(Pos.CENTER); + postLabel.setTextAlignment(TextAlignment.LEFT); + postLabel.setAlignment(Pos.CENTER_LEFT); + + advLabel.setAlignment(Pos.CENTER); +// advLabel.prefColumnCountProperty().bind(advLabel.textProperty().length().subtract(3)); + // Set Max and Min Width to PREF_SIZE so that the TextField is always PREF + advLabel.setMinWidth(Region.USE_PREF_SIZE); + advLabel.setMaxWidth(Region.USE_PREF_SIZE); + + //pretty complicated to make sure the text field is the same size as the text that is being typed. + advLabel.textProperty().addListener((ov, prevText, currText) -> { + // Do this in a Platform.runLater because of Textfield has no padding at first time and so on + Platform.runLater(() -> { + Text text = new Text(currText); + text.setFont(advLabel.getFont()); // Set the same font, so the size is the same + double width = text.getLayoutBounds().getWidth() // This big is the Text in the TextField + + advLabel.getPadding().getLeft() + advLabel.getPadding().getRight() // Add the padding of the TextField + + 2d; // Add some spacing + advLabel.setPrefWidth(width); // Set the width + advLabel.positionCaret(advLabel.getCaretPosition()); // If you remove this line, it flashes a little bit + }); + }); + advLabel.setId("label-title2"); + advLabel.setStyle("-fx-background-color: transparent"); + + titleHolder.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center. + + //holds the back button and the title pane. PamHBox buttonHolder = new PamHBox(); - buttonHolder.setBackground(null); //buttonHolder.setStyle("-fx-background-color: red;"); buttonHolder.setAlignment(Pos.CENTER_LEFT); - buttonHolder.getChildren().addAll(backButton, advLabel = new Label("Adv. Settings")); + buttonHolder.getChildren().addAll(backButton, titleHolder); + advLabel.setAlignment(Pos.CENTER); advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center. - PamGuiManagerFX.titleFont2style(advLabel); - +// PamGuiManagerFX.titleFont2style(advLabel); + + advLabel.setAlignment(Pos.CENTER); - HBox.setHgrow(advLabel, Priority.ALWAYS); + HBox.setHgrow(titleHolder, Priority.ALWAYS); advPane.setTop(buttonHolder); @@ -117,16 +203,45 @@ public class PamFlipPane extends FlipPane { } - public Label getAdvLabel() { + public TextField getAdvLabel() { return advLabel; } - public void setAdvLabel(Label advLabel) { - this.advLabel = advLabel; - } +// public void setAdvLabel(Label advLabel) { +// this.advLabel = advLabel; +// } public PamButton getBackButton() { return backButton; } + + /** + * Get the label located before the editable label in the title + * @return the label before the editable label + */ + public Label getPreAdvLabel() { + return preLabel; + } + + /** + * Get the label located after the editable label in the title + * @return the label after the editable label + */ + public Label getPostAdvLabel() { + return postLabel; + } + + /** + * True if the flip pane is showing the front. + */ + public boolean isShowingFront() { + return super.flipFrontProperty().get(); + } + + public void setAdvLabelEditable(boolean b) { + this.advLabel.setEditable(b); + + } + } diff --git a/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java b/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java index c758442f..33eb11c1 100644 --- a/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java +++ b/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java @@ -143,7 +143,7 @@ public class FilterPaneFX extends SettingsPane { } else { mainPane.setTop(createFilterPane()); - mainPane.setBottom(createBodeGraph()); + mainPane.setCenter(createBodeGraph()); } } diff --git a/src/pamViewFX/fxNodes/utilityPanes/LatLongPane.java b/src/pamViewFX/fxNodes/utilityPanes/LatLongPane.java index 6edc9771..711491dd 100644 --- a/src/pamViewFX/fxNodes/utilityPanes/LatLongPane.java +++ b/src/pamViewFX/fxNodes/utilityPanes/LatLongPane.java @@ -1,19 +1,24 @@ package pamViewFX.fxNodes.utilityPanes; +import org.controlsfx.control.SegmentedButton; + import PamController.SettingsPane; import PamUtils.LatLong; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; -import javafx.scene.control.RadioButton; -import javafx.scene.control.ToggleGroup; -import pamViewFX.fxNodes.PamBorderPane; +import javafx.scene.control.Toggle; +import javafx.scene.control.ToggleButton; +import javafx.scene.text.TextAlignment; +import pamViewFX.PamGuiManagerFX; import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamVBox; /** * Pane with controls to to set the values for a Latitude and Longitude. The pane allows users to * change the Latitude and Longitude in both Degrees, Decimal minutes and Degrees, Minutes, Seconds + * * @author Jamie Macaulay * */ @@ -27,37 +32,62 @@ public class LatLongPane extends SettingsPane{ /** * The radio button to select decimal minutes */ - private RadioButton decimalMinutes; + private ToggleButton decimalMinutes; /** * Radio button to input minutes and seconds. */ - private RadioButton minutesSeconds; + private ToggleButton minutesSeconds; /** * Lat long strip */ private LatLongStrip latStrip, longStrip; - private PamBorderPane mainPane; + private PamVBox mainPane; + + private ToggleButton decimal; + + /** + * Segmented button that also selection of the latitude and longitude format type. + */ + private SegmentedButton segmentedButton; public LatLongPane(String title) { super(null); + + + mainPane = new PamVBox(); + mainPane.setSpacing(5); + mainPane.setAlignment(Pos.CENTER); + + + Label titleLabel = new Label(title); + titleLabel.maxWidth(Double.MAX_VALUE); + titleLabel.setTextAlignment(TextAlignment.LEFT); + PamGuiManagerFX.titleFont2style(titleLabel); + mainPane.getChildren().add(titleLabel); + latLong= new LatLong(); - mainPane = new PamBorderPane(); + + decimalMinutes = new ToggleButton("Degrees, Decimal minutes"); + minutesSeconds = new ToggleButton("Degrees, Minutes, Seconds"); + decimal = new ToggleButton("Decimal"); + + segmentedButton = new SegmentedButton(); + segmentedButton.getButtons().addAll(decimalMinutes, minutesSeconds, decimal); PamHBox top = new PamHBox(); top.setSpacing(5); - top.getChildren().add(new Label("Unit type :")); - top.getChildren().add(decimalMinutes = new RadioButton("Degrees, Decimal minutes")); - top.getChildren().add(minutesSeconds = new RadioButton("Degrees, Minutes, Seconds")); + top.getChildren().add(segmentedButton); - ToggleGroup bg = new ToggleGroup(); - decimalMinutes.setToggleGroup(bg); - minutesSeconds.setToggleGroup(bg); + // ToggleGroup bg = new ToggleGroup(); + // decimalMinutes.setToggleGroup(bg); + // minutesSeconds.setToggleGroup(bg); + // decimal.setToggleGroup(bg); decimalMinutes.setOnAction((action)->{ actionPerformed(action); @@ -66,7 +96,12 @@ public class LatLongPane extends SettingsPane{ minutesSeconds.setOnAction((action)->{ actionPerformed(action); }); - mainPane.setTop(top); + + decimal.setOnAction((action)->{ + actionPerformed(action); + }); + + mainPane.getChildren().add(top); PamVBox cent = new PamVBox(); cent.setSpacing(5); @@ -75,8 +110,12 @@ public class LatLongPane extends SettingsPane{ cent.getChildren().add(latStrip = new LatLongStrip(true)); cent.getChildren().add(longStrip = new LatLongStrip(false)); - mainPane.setCenter(cent); + //bit of a hack that makes sure controls are aligned for the latitude and longitude. + latStrip.getTitleLabel().prefWidthProperty().bind(longStrip.getTitleLabel().widthProperty()); + mainPane.getChildren().add(cent); + + decimal.setSelected(true); } @@ -85,16 +124,17 @@ public class LatLongPane extends SettingsPane{ */ public void actionPerformed(javafx.event.ActionEvent action) { + if (action.getSource() == decimalMinutes) { LatLong.setFormatStyle(LatLong.FORMAT_DECIMALMINUTES); - // if (latStrip != null) { - // latStrip.setDecimalMinutes(true); - // longStrip.setDecimalMinutes(true); - // } + // if (latStrip != null) { + // latStrip.setDecimalMinutes(true); + // longStrip.setDecimalMinutes(true); + // } latStrip.showControls(LatLong.FORMAT_DECIMALMINUTES); longStrip.showControls(LatLong.FORMAT_DECIMALMINUTES); } - else if (action.getSource() == minutesSeconds) { + else if (action.getSource() == minutesSeconds){ LatLong.setFormatStyle(LatLong.FORMAT_MINUTESSECONDS); // if (latStrip != null) { // latStrip.setDecimalMinutes(false); @@ -105,19 +145,26 @@ public class LatLongPane extends SettingsPane{ latStrip.showControls(LatLong.FORMAT_MINUTESSECONDS); longStrip.showControls(LatLong.FORMAT_MINUTESSECONDS); } - + else if (action.getSource() == decimal){ + LatLong.setFormatStyle(LatLong.FORMAT_DECIMAL); + latStrip.showControls(LatLong.FORMAT_DECIMAL); + longStrip.showControls(LatLong.FORMAT_DECIMAL); + } } private void showLatLong() { - decimalMinutes.setSelected(LatLong.getFormatStyle() == LatLong.FORMAT_DECIMALMINUTES); - minutesSeconds.setSelected(LatLong.getFormatStyle() == LatLong.FORMAT_MINUTESSECONDS); - latStrip.showControls(LatLong.getFormatStyle() ); - longStrip.showControls(LatLong.getFormatStyle() ); - latStrip.sayValue(latLong.getLatitude()); - longStrip.sayValue(latLong.getLongitude()); + + decimalMinutes .setSelected(LatLong.getFormatStyle() == LatLong.FORMAT_DECIMALMINUTES); + minutesSeconds .setSelected(LatLong.getFormatStyle() == LatLong.FORMAT_MINUTESSECONDS); + decimal .setSelected(LatLong.getFormatStyle() == LatLong.FORMAT_DECIMAL); + + latStrip .showControls(LatLong.getFormatStyle() ); + longStrip .showControls(LatLong.getFormatStyle() ); + latStrip .setValue(latLong.getLatitude()); + longStrip .setValue(latLong.getLongitude()); } @@ -127,6 +174,21 @@ public class LatLongPane extends SettingsPane{ */ @Override public LatLong getParams(LatLong currentParams) { + + Toggle selectedButton = this.segmentedButton.getToggleGroup().getSelectedToggle(); + + if (selectedButton == decimalMinutes) { + LatLong.setFormatStyle(LatLong.FORMAT_DECIMALMINUTES); + + } + else if (selectedButton == minutesSeconds){ + LatLong.setFormatStyle(LatLong.FORMAT_MINUTESSECONDS); + + } + else if (selectedButton == decimal){ + LatLong.setFormatStyle(LatLong.FORMAT_DECIMAL); + } + latLong = new LatLong(latStrip.getValue(), longStrip.getValue()); if (Double.isNaN(latLong.getLatitude()) || Double.isNaN(latLong.getLongitude())) { return null; diff --git a/src/pamViewFX/fxNodes/utilityPanes/LatLongStrip.java b/src/pamViewFX/fxNodes/utilityPanes/LatLongStrip.java index 2073dace..2e80e8f0 100644 --- a/src/pamViewFX/fxNodes/utilityPanes/LatLongStrip.java +++ b/src/pamViewFX/fxNodes/utilityPanes/LatLongStrip.java @@ -17,24 +17,30 @@ import pamViewFX.fxNodes.PamHBox; * */ public class LatLongStrip extends PamBorderPane { - + Label formattedText; - TextField degrees, minutes, seconds, decminutes; - Label dl, ml, sl, dml; + TextField degrees, minutes, seconds, decminutes, decimal; + Label dl, ml, sl, dml, dec; ComboBox nsew; boolean isLatitude; -// boolean decimalMinutes = true; - + // boolean decimalMinutes = true; + /** * HBox to hold decimal minutes, degrees, seconds controls. */ private PamHBox degHBox; - + /** * HBox to hold decimal controls */ private PamHBox decHBox; - + + /** + * The format type e.g. LatLong.FORMAT_DECIMALMINUTES. + */ + private int formatType = LatLong.FORMAT_DECIMALMINUTES; + private Label titleLabel; + /** * Construct a strip of controls to include in a larger dialog. @@ -48,7 +54,7 @@ public class LatLongStrip extends PamBorderPane { isLatitude = latitude; createDialogStrip(showBorder); } - + /** * Construct a strip of controls to include in a larger dialog. *

By default the strip will have a titled border with the @@ -59,27 +65,33 @@ public class LatLongStrip extends PamBorderPane { isLatitude = latitude; createDialogStrip(true); } - + private void createDialogStrip(boolean showBorder) { - - String borderTitle; - if (isLatitude) borderTitle = "Latitude"; - else borderTitle = "Longitude"; - - Label title= new Label(borderTitle); - PamGuiManagerFX.titleFont2style(title); -// title.setFont(PamGuiManagerFX.titleFontSize2); + + String title; + if (isLatitude) title = "Latitude"; + else title = "Longitude"; + + // title.setFont(PamGuiManagerFX.titleFontSize2); degrees = new TextField(); + degrees.setEditable(true); degrees.setPrefColumnCount(4); minutes = new TextField(); minutes.setPrefColumnCount(3); + minutes.setEditable(true); seconds = new TextField(); seconds.setPrefColumnCount(6); + seconds.setEditable(true); decminutes = new TextField(); decminutes.setPrefColumnCount(6); - + decminutes.setEditable(true); + + decimal=new TextField(); + decimal.setPrefColumnCount(9); + decimal.setEditable(true); + nsew = new ComboBox(); nsew.setOnAction((action)->{ double v = getValue(); @@ -91,6 +103,8 @@ public class LatLongStrip extends PamBorderPane { ml = new Label("min."); sl = new Label("sec."); dml = new Label("dec min."); + dec = new Label("decimal deg."); + formattedText = new Label("Position"); if (isLatitude) { nsew.getItems().add("N"); @@ -100,123 +114,192 @@ public class LatLongStrip extends PamBorderPane { nsew.getItems().add("E"); nsew.getItems().add("W"); } - + degrees.setOnKeyPressed((key)->{ newTypedValues(key); }); - + minutes.setOnKeyPressed((key)->{ newTypedValues(key); }); - + seconds.setOnKeyPressed((key)->{ newTypedValues(key); }); - + decminutes.setOnKeyPressed((key)->{ newTypedValues(key); }); - + + decimal.setOnKeyPressed((key)->{ + newTypedValues(key); + }); + nsew.setOnKeyPressed((key)->{ newTypedValues(key); }); - + degHBox = new PamHBox(); degHBox.setSpacing(5); degHBox.setAlignment(Pos.CENTER_LEFT); - - this.setRight(nsew); - this.setCenter(degHBox); + + PamHBox holder= new PamHBox(); + holder.setAlignment(Pos.CENTER_LEFT); + holder.setSpacing(5); + holder.getChildren().addAll(titleLabel = new Label(title), degHBox, nsew); + + this.setCenter(holder); this.setBottom(formattedText); - showControls( LatLong.FORMAT_DECIMALMINUTES); + showControls(formatType); } private void newTypedValues(KeyEvent e) { double v = getValue(); - // now need to put that into the fields that - // are not currently shown so that they are - // ready if needed. - if (e != null) { - sayValue(v, true); - } +// // now need to put that into the fields that +// // are not currently shown so that they are +// // ready if needed. +// +// if (e != null) { +// setValue(v, true); +// } + // and say the formated version sayFormattedValue(v); } - + public void showControls(int formatStyle) { - boolean decimal = (formatStyle == LatLong.FORMAT_DECIMALMINUTES); + + if (formatType==formatStyle) { + return; + } + + //important this comes before setting format style. + double currentValue = getValue(); + + this.formatType = formatStyle; + degHBox.getChildren().clear(); - if (decimal) { + + System.out.println("FORMATSTYLE: " + formatStyle + " val " + currentValue); + + switch (formatType) { + case LatLong.FORMAT_DECIMALMINUTES: degHBox.getChildren().add(dl); degHBox.getChildren().add(degrees); degHBox.getChildren().add(dml); degHBox.getChildren().add(decminutes); - } - else { + break; + case LatLong.FORMAT_MINUTESSECONDS: degHBox.getChildren().add(dl); degHBox.getChildren().add(degrees); degHBox.getChildren().add(ml); degHBox.getChildren().add(minutes); degHBox.getChildren().add(sl); degHBox.getChildren().add(seconds); + break; + case LatLong.FORMAT_DECIMAL: + degHBox.getChildren().add(dec); + degHBox.getChildren().add(decimal); + break; + } - minutes.setVisible(decimal == false); - ml.setVisible(decimal == false); - seconds.setVisible(decimal == false); - sl.setVisible(decimal == false); - decminutes.setVisible(decimal); - dml.setVisible(decimal); + + setValue(currentValue); + sayFormattedValue(getValue()); } - + /** * Set data in the lat long dialog strip * @param value Lat or Long in decimal degrees. */ - public void sayValue(double value) { - sayValue(value, false); + public void setValue(double value) { + setValue(value, false); } - - public void sayValue(double value, boolean hiddenOnly) { + + public void setValue(double value, boolean hiddenOnly) { + + System.out.println("Set value: " + value); if (value >= 0) { nsew.getSelectionModel().select(0); } else { nsew.getSelectionModel().select(1); } - + double deg = LatLong.getSignedDegrees(value); -// System.out.println("Deg: " + LatLong.getSignedDegrees(value) + " value: " +value); - - if (degrees.isVisible() == false || !hiddenOnly) degrees.setText(String.format("%d", (int)Math.abs(deg))); - if (minutes.isVisible() == false || !hiddenOnly) minutes.setText(String.format("%d", LatLong.getIntegerMinutes(value))); - if (decminutes.isVisible() == false || !hiddenOnly) decminutes.setText(String.format("%3.5f", LatLong.getDecimalMinutes(value))); - if (seconds.isVisible() == false || !hiddenOnly) seconds.setText(String.format("%3.5f", LatLong.getSeconds(value))); - if (nsew.isVisible() == false || !hiddenOnly) nsew.getSelectionModel().select(deg >= 0 ? 0 : 1); + // System.out.println("Deg: " + LatLong.getSignedDegrees(value) + " value: " +value); + + + // if (degrees.isVisible() == false || !hiddenOnly) degrees.setText(String.format("%d", (int)Math.abs(deg))); + // if (minutes.isVisible() == false || !hiddenOnly) minutes.setText(String.format("%d", LatLong.getIntegerMinutes(value))); + // if (decminutes.isVisible() == false || !hiddenOnly) decminutes.setText(String.format("%3.5f", LatLong.getDecimalMinutes(value))); + // if (seconds.isVisible() == false || !hiddenOnly) seconds.setText(String.format("%3.5f", LatLong.getSeconds(value))); + // if (nsew.isVisible() == false || !hiddenOnly) nsew.getSelectionModel().select(deg >= 0 ? 0 : 1); + // if (decimal.isVisible() == false || !hiddenOnly) decimal.setText(String.format("%.8f", value)); + + switch (formatType) { + case LatLong.FORMAT_DECIMALMINUTES: + + degrees.setText(String.format("%d", (int)Math.abs(deg))); + decminutes.setText(String.format("%3.5f", LatLong.getDecimalMinutes(value))); + + break; + case LatLong.FORMAT_MINUTESSECONDS: + + degrees.setText(String.format("%d", (int)Math.abs(deg))); + minutes.setText(String.format("%d", LatLong.getIntegerMinutes(value))); + seconds.setText(String.format("%3.5f", LatLong.getSeconds(value))); + + break; + case LatLong.FORMAT_DECIMAL: + + decimal.setText(String.format("%.8f", value)); + + break; + + } + sayFormattedValue(value); } - + /** - * Get the value for the latitude and longitude - * @return the value. + * Get the value for the latitude or longitude in decimal + * @return the value - the value in decimal */ public double getValue() { + double deg = 0; double min = 0; double sec = 0; double sin = 1.; - if (nsew.getSelectionModel().getSelectedIndex()== 1) sin = -1.; + + if (nsew.getSelectionModel().getSelectedIndex() == 1) sin = -1.; + + + if (formatType == LatLong.FORMAT_DECIMAL){ + try { + deg = Double.valueOf(decimal.getText()); + return deg; + } + catch (NumberFormatException ex) { + return Double.NaN; + } + } + try { - deg = Integer.valueOf(degrees.getText()); + deg = Integer.valueOf(degrees.getText()); } catch (NumberFormatException Ex) { return Double.NaN; } - if (LatLong.getFormatStyle() == LatLong.FORMAT_DECIMALMINUTES){ + + + if (formatType == LatLong.FORMAT_DECIMALMINUTES){ try { min = Double.valueOf(decminutes.getText()); } @@ -237,12 +320,13 @@ public class LatLongStrip extends PamBorderPane { catch (NumberFormatException ex) { return Double.NaN; } + } deg += min/60 + sec/3600; deg *= sin; return deg; } - + /** * Clear the latitude/longitude data from the pane. */ @@ -251,9 +335,10 @@ public class LatLongStrip extends PamBorderPane { minutes.setText(""); seconds.setText(""); decminutes.setText(""); + decimal.setText(""); } - - + + public void sayFormattedValue(double value) { if (isLatitude) { formattedText.setText(LatLong.formatLatitude(value)); @@ -262,13 +347,13 @@ public class LatLongStrip extends PamBorderPane { formattedText.setText(LatLong.formatLongitude(value)); } } -// public boolean isDecimalMinutes() { -// return decimalMinutes; -// } -// public void setDecimalMinutes(boolean decimalMinutes) { -// this.decimalMinutes = decimalMinutes; -// showControls(); -// } + // public boolean isDecimalMinutes() { + // return decimalMinutes; + // } + // public void setDecimalMinutes(boolean decimalMinutes) { + // this.decimalMinutes = decimalMinutes; + // showControls(); + // } /** * Set the pane to be enabled or disabled. @@ -281,5 +366,16 @@ public class LatLongStrip extends PamBorderPane { seconds.setDisable(!enabled); decminutes.setDisable(!enabled); nsew.setDisable(!enabled); + decimal.setDisable(!enabled); } + + /** + * Get the title label. + * @return the title label. + */ + public Label getTitleLabel() { + return titleLabel; + } + + } diff --git a/src/pamViewFX/fxNodes/utilsFX/TextUtilsFX.java b/src/pamViewFX/fxNodes/utilsFX/TextUtilsFX.java new file mode 100644 index 00000000..d47098d7 --- /dev/null +++ b/src/pamViewFX/fxNodes/utilsFX/TextUtilsFX.java @@ -0,0 +1,40 @@ +package pamViewFX.fxNodes.utilsFX; + +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.scene.text.TextBoundsType; + +public class TextUtilsFX { + + static final Text helper; + static final double DEFAULT_WRAPPING_WIDTH; + static final double DEFAULT_LINE_SPACING; + static final String DEFAULT_TEXT; + static final TextBoundsType DEFAULT_BOUNDS_TYPE; + static { + helper = new Text(); + DEFAULT_WRAPPING_WIDTH = helper.getWrappingWidth(); + DEFAULT_LINE_SPACING = helper.getLineSpacing(); + DEFAULT_TEXT = helper.getText(); + DEFAULT_BOUNDS_TYPE = helper.getBoundsType(); + } + + public static double computeTextWidth(Font font, String text, double help0) { + // Toolkit.getToolkit().getFontLoader().computeStringWidth(field.getText(), + // field.getFont()); + + helper.setText(text); + helper.setFont(font); + + helper.setWrappingWidth(0.0D); + helper.setLineSpacing(0.0D); + double d = Math.min(helper.prefWidth(-1.0D), help0); + helper.setWrappingWidth((int) Math.ceil(d)); + d = Math.ceil(helper.getLayoutBounds().getWidth()); + + helper.setWrappingWidth(DEFAULT_WRAPPING_WIDTH); + helper.setLineSpacing(DEFAULT_LINE_SPACING); + helper.setText(DEFAULT_TEXT); + return d; + } +} \ No newline at end of file