From 8a9719b425144868f6807c711e556db75604d1eb Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Mon, 1 May 2023 18:55:35 +0100 Subject: [PATCH] Tethys working again And a bit more playing around with metadata handling for Deploymnet documents --- .classpath | 4 +- src/Array/Hydrophone.java | 4 +- src/PamModel/PamModel.java | 3 +- .../sqlite/SqliteSQLTypes.java | 2 +- src/metadata/deployment/DeploymentData.java | 57 ++++++++++ src/tethys/TethysControl.java | 3 +- src/tethys/dbxml/DBXMLConnect.java | 65 ++++++++++- src/tethys/dbxml/DBXMLQueries.java | 3 + src/tethys/deployment/DeploymentHandler.java | 81 ++++++++++++-- src/tethys/deployment/DutyCycleInfo.java | 5 +- src/tethys/detection/DetectionsHandler.java | 2 +- src/tethys/niluswraps/PDescriptionType.java | 101 ++++++++++++++++++ src/tethys/output/StreamExportParams.java | 16 ++- src/tethys/swing/DeploymentExportPanel.java | 6 ++ src/tethys/swing/FancyClientButton.java | 84 +++++++++++++++ .../swing/PAMGuardDeploymentsTable.java | 65 +++++++++-- src/tethys/swing/TethysConnectionPanel.java | 6 +- .../swing/export/DescriptionTypePanel.java | 5 +- 18 files changed, 476 insertions(+), 36 deletions(-) create mode 100644 src/tethys/niluswraps/PDescriptionType.java create mode 100644 src/tethys/swing/FancyClientButton.java diff --git a/.classpath b/.classpath index 4339aee1..8f3f9191 100644 --- a/.classpath +++ b/.classpath @@ -6,7 +6,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/src/Array/Hydrophone.java b/src/Array/Hydrophone.java index d726f0b8..2ec068d7 100644 --- a/src/Array/Hydrophone.java +++ b/src/Array/Hydrophone.java @@ -158,7 +158,7 @@ public class Hydrophone implements Serializable, Cloneable, ManagedParameters { return sensitivity; } - protected void setSensitivity(double sensitivity) { + public void setSensitivity(double sensitivity) { this.sensitivity = sensitivity; } @@ -364,7 +364,7 @@ public class Hydrophone implements Serializable, Cloneable, ManagedParameters { /** * @param preampGain The preampGain to set. */ - protected void setPreampGain(double preampGain) { + public void setPreampGain(double preampGain) { this.preampGain = preampGain; } diff --git a/src/PamModel/PamModel.java b/src/PamModel/PamModel.java index 055a7989..003d657b 100644 --- a/src/PamModel/PamModel.java +++ b/src/PamModel/PamModel.java @@ -46,8 +46,6 @@ import fftManager.PamFFTControl; import group3dlocaliser.Group3DLocaliserControl; import metadata.MetaDataContol; import meygenturbine.MeygenTurbine; -import networkTransfer.receive.BuoyStatusDataUnit; -import networkTransfer.receive.NetworkReceiver; import printscreen.PrintScreenControl; import rockBlock.RockBlockControl; import tethys.TethysControl; @@ -1098,6 +1096,7 @@ final public class PamModel implements PamModelInterface, PamSettings { * PamModel ! */ +// pluginList.add(new MorlaisWP1aPlugin()); // Load up whatever default classloader was used to create this class. Must use the same classloader // for all plugins, or else we will not be able to create proper dependencies between them or be able diff --git a/src/generalDatabase/sqlite/SqliteSQLTypes.java b/src/generalDatabase/sqlite/SqliteSQLTypes.java index 580c8c5e..4f2baf73 100644 --- a/src/generalDatabase/sqlite/SqliteSQLTypes.java +++ b/src/generalDatabase/sqlite/SqliteSQLTypes.java @@ -10,7 +10,7 @@ import PamUtils.PamCalendar; public class SqliteSQLTypes extends SQLTypes { - protected static final SQLiteConfig.DateClass dateClass = SQLiteConfig.DateClass.TEXT; + public static final SQLiteConfig.DateClass dateClass = SQLiteConfig.DateClass.TEXT; @Override public String typeToString(int sqlType, int length, boolean counter) { diff --git a/src/metadata/deployment/DeploymentData.java b/src/metadata/deployment/DeploymentData.java index 3f7e351b..d9aaaf19 100644 --- a/src/metadata/deployment/DeploymentData.java +++ b/src/metadata/deployment/DeploymentData.java @@ -5,6 +5,7 @@ import java.io.Serializable; import PamModel.parametermanager.FieldNotFoundException; import PamModel.parametermanager.ManagedParameters; import PamModel.parametermanager.PamParameterSet; +import PamUtils.LatLong; /** * Class to hold Deployment data in a form consistent with the ANSI PAM @@ -65,6 +66,46 @@ public class DeploymentData implements Serializable, Cloneable, ManagedParameter * Name of geographic region. */ private String region; + + /** + * time of instrument deployment (different to recording start); + */ + private Long deploymentMillis; + + /** + * time of actual recovery (different to recording end); + */ + private Long recoveryMillis; + + private LatLong recoverLatLong; + + /** + * @return the deploymentMillis + */ + public Long getDeploymentMillis() { + return deploymentMillis; + } + + /** + * @param deploymentMillis the deploymentMillis to set + */ + public void setDeploymentMillis(Long deploymentMillis) { + this.deploymentMillis = deploymentMillis; + } + + /** + * @return the recoveryMillis + */ + public Long getRecoveryMillis() { + return recoveryMillis; + } + + /** + * @param recoveryMillis the recoveryMillis to set + */ + public void setRecoveryMillis(Long recoveryMillis) { + this.recoveryMillis = recoveryMillis; + } // /** // * Instrument type, e.g. HARP, EAR, Popup, DMON, etc. @@ -235,6 +276,22 @@ public class DeploymentData implements Serializable, Cloneable, ManagedParameter this.region = region; } + /** + * Set the recovery position latlong for a static recorder. + * Deployment lat long is in the hydrophone array data. + * @param recoverLatLong + */ + public void setRecoveryLatLong(LatLong recoverLatLong) { + this.recoverLatLong = recoverLatLong; + } + + /** + * @return the recoverLatLong (may often be null) + */ + public LatLong getRecoverLatLong() { + return recoverLatLong; + } + // /** // * @return the instrumentType // */ diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java index ec7bb23a..7d3a0e48 100644 --- a/src/tethys/TethysControl.java +++ b/src/tethys/TethysControl.java @@ -412,7 +412,8 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet public void notifyModelChanged(int changeType) { super.notifyModelChanged(changeType); switch (changeType) { - case PamControllerInterface.INITIALIZATION_COMPLETE: + case PamControllerInterface.INITIALIZE_LOADDATA: +// case PamControllerInterface.INITIALIZATION_COMPLETE: initializationStuff(); break; } diff --git a/src/tethys/dbxml/DBXMLConnect.java b/src/tethys/dbxml/DBXMLConnect.java index 3dff4c3b..e7b54820 100644 --- a/src/tethys/dbxml/DBXMLConnect.java +++ b/src/tethys/dbxml/DBXMLConnect.java @@ -1,9 +1,15 @@ package tethys.dbxml; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.file.Files; import java.util.ArrayList; import javax.xml.bind.JAXBException; @@ -31,6 +37,8 @@ public class DBXMLConnect { private Queries queries; private String currentSiteURL; + + public static String[] collections = {"Deployments", "Detections", "Localizations", "Calibrations", "SpeciesAbbreviations"}; public DBXMLConnect(TethysControl tethysControl) { this.tethysControl = tethysControl; @@ -136,13 +144,15 @@ public class DBXMLConnect { String tempName = getTempFileName(nilusObject); tempName = tempDirectory.getAbsolutePath() + File.separator + tempName + ".xml"; File tempFile = new File(tempName); + String bodgeName = tempName;//"C:\\Users\\dg50\\AppData\\Local\\Temp\\PAMGuardTethys\\Meygen2022_10a.xml"; try { MarshalXML marshal = new MarshalXML(); marshal.createInstance(objClass); // Path tempFile = Files.createTempFile("pamGuardToTethys", ".xml"); marshal.marshal(nilusObject, tempFile.toString()); +// tempFile = stripXMLHeader(tempFile); fileError = Importer.ImportFiles(params.getFullServerName(), collection, - new String[] { tempFile.toString() }, "", "", false); + new String[] { bodgeName }, "", "", false); // System.out.println(fileError); @@ -157,11 +167,62 @@ public class DBXMLConnect { // TODO Auto-generated catch block e.printStackTrace(); } -// System.out.println(fileError); + System.out.println(fileError); return fileError; } + /** + * Seems we have to get rid of the line + * which is being put there by the marshaller ? + * @param tempFile + */ + private File stripXMLHeader(File tempFile) { + // TODO Auto-generated method stub + + File tempTemp = new File(tempFile.getAbsolutePath().replace(".temp.xml", ".xml")); + try { + BufferedReader reader = new BufferedReader(new FileReader(tempFile)); + BufferedWriter writer = new BufferedWriter(new FileWriter(tempTemp)); + String line = reader.readLine(); + while (line != null) { + // see if the line has any unicode in it + int len = line.length(); + byte[] bytes = line.getBytes(); + if (len == bytes.length) { + System.out.println(line); + } + + if (line.startsWith(" getProjectDeployments(String projectName) { + if (projectName == null) { + return null; + } String qBase = "{\"return\":[\"Deployment\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"%s\"],\"optype\":\"binary\"}],\"enclose\":1}"; String qStr = String.format(qBase, projectName); diff --git a/src/tethys/deployment/DeploymentHandler.java b/src/tethys/deployment/DeploymentHandler.java index 578a3c99..a87f8d30 100644 --- a/src/tethys/deployment/DeploymentHandler.java +++ b/src/tethys/deployment/DeploymentHandler.java @@ -2,6 +2,8 @@ package tethys.deployment; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.ListIterator; @@ -21,6 +23,8 @@ import Array.Streamer; import Array.ThreadingHydrophoneLocator; import PamController.PamControlledUnit; import PamController.PamController; +import PamUtils.LatLong; +import PamUtils.PamCalendar; import PamUtils.PamUtils; import PamguardMVC.PamDataBlock; import SoundRecorder.RecordingInfo; @@ -156,6 +160,20 @@ public class DeploymentHandler implements TethysStateObserver { // just load everything. Probably OK for the acqusition, but will bring down daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null); ArrayList allStatusData = daqInfoDataBlock.getDataCopy(); + /** + * Due to seird file overlaps we need to resort this by id if we can. + * + */ + Collections.sort(allStatusData, new Comparator() { + + @Override + public int compare(DaqStatusDataUnit o1, DaqStatusDataUnit o2) { + if (o1.getDatabaseIndex() == 0) { + return (int) (o1.getTimeMilliseconds()-o2.getTimeMilliseconds()); + } + return o1.getDatabaseIndex()-o2.getDatabaseIndex(); + } + }); ArrayList tempPeriods = null; @@ -168,8 +186,15 @@ public class DeploymentHandler implements TethysStateObserver { } if (tempPeriods == null || tempPeriods.size() == 0) { System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings."); + return null; } + int nPeriods = tempPeriods.size(); +// int i = 0; +// for (RecordingPeriod aP : tempPeriods) { +// System.out.printf("Pre merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()), +// PamCalendar.formatDBDateTime(aP.getRecordStop())); +// } // now go through those and merge into longer periods where there is no gap between files. ListIterator iterator = tempPeriods.listIterator(); RecordingPeriod prevPeriod = null; @@ -191,6 +216,11 @@ public class DeploymentHandler implements TethysStateObserver { } prevPeriod = nextPeriod; } +// i = 0; +// for (RecordingPeriod aP : tempPeriods) { +// System.out.printf("Post merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()), +// PamCalendar.formatDBDateTime(aP.getRecordStop())); +// } // System.out.printf("Data have %d distinct files, but only %d distinct recording periods\n", nPeriods, tempPeriods.size()); DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods); // if it's duty cycles, then we only want a single entry. @@ -202,6 +232,17 @@ public class DeploymentHandler implements TethysStateObserver { deploymentPeriods = new ArrayList<>(); deploymentPeriods.add(new RecordingPeriod(tempPeriods.get(0).getRecordStart(), tempPeriods.get(tempPeriods.size()-1).getRecordStop())); } + /* + * do another sort of the deploymentPeriods. The start stops were in the order they went into the + * database in the hope that pairs were the right way round. Now check all data are/ + */ + Collections.sort(deploymentPeriods, new Comparator() { + @Override + public int compare(RecordingPeriod o1, RecordingPeriod o2) { + return (int) (o1.getRecordStart()-o2.getRecordStart()); + } + }); + DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods); matchPamguard2Tethys(deploymentOverview, projectDeployments); this.deploymentOverview = deploymentOverview; @@ -300,7 +341,6 @@ public class DeploymentHandler implements TethysStateObserver { return cycleInfo; } - private ArrayList extractTimesFromStatus(ArrayList allStatusData) { ArrayList tempPeriods = new ArrayList<>(); long dataStart = Long.MAX_VALUE; @@ -315,14 +355,20 @@ public class DeploymentHandler implements TethysStateObserver { nStart++; dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds()); lastStart = daqStatus.getTimeMilliseconds(); +// System.out.println("Start at " + PamCalendar.formatDBDateTime(lastStart)); break; case "Stop": nStop++; dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds()); long lastEnd = daqStatus.getEndTimeInMilliseconds(); if (lastStart != null) { +// System.out.printf("Adding period %s to %s\n", PamCalendar.formatDBDateTime(lastStart), +// PamCalendar.formatDBDateTime(lastEnd)); tempPeriods.add(new RecordingPeriod(lastStart, lastEnd)); } + else { +// System.out.println("Skipping stop at " + PamCalendar.formatDBDateTime(lastEnd)); + } lastStart = null; break; case "NextFile": @@ -505,16 +551,23 @@ public class DeploymentHandler implements TethysStateObserver { e.printStackTrace(); } DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData(); - String id = String.format("%s%d", globalDeplData.getProject(), i); + String id = String.format("%s_%d", globalDeplData.getProject(), i); deployment.setId(id); deployment.setDeploymentId(i); - DeploymentRecoveryDetails deploymentDetails = new DeploymentRecoveryDetails(); - DeploymentRecoveryDetails recoveryDetails = new DeploymentRecoveryDetails(); - deploymentDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart())); + DeploymentRecoveryDetails deploymentDetails = deployment.getDeploymentDetails(); + if (deploymentDetails == null) { + deploymentDetails = new DeploymentRecoveryDetails(); + } + DeploymentRecoveryDetails recoveryDetails = deployment.getRecoveryDetails(); + if (recoveryDetails == null) { + recoveryDetails = new DeploymentRecoveryDetails(); + } deploymentDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart())); - recoveryDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop())); recoveryDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop())); + + deploymentDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart())); + recoveryDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop())); deployment.setDeploymentDetails(deploymentDetails); deployment.setRecoveryDetails(recoveryDetails); @@ -572,6 +625,22 @@ public class DeploymentHandler implements TethysStateObserver { String geomType = getGeometryType(); instrument.setGeometryType(geomType); deployment.setInstrument(instrument); + + // overwrite the default deployment and recovery times if there is non null data + Long depMillis = deploymentData.getDeploymentMillis(); + if (depMillis != null) { + deployment.getDeploymentDetails().setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(depMillis)); + } + Long recMillis = deploymentData.getRecoveryMillis(); + if (recMillis != null) { + deployment.getRecoveryDetails().setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recMillis)); + } + LatLong recLatLong = deploymentData.getRecoverLatLong(); + if (recLatLong != null) { + deployment.getRecoveryDetails().setLatitude(recLatLong.getLatitude()); + deployment.getRecoveryDetails().setLongitude(PamUtils.constrainedAngle(recLatLong.getLongitude())); + } + return true; } diff --git a/src/tethys/deployment/DutyCycleInfo.java b/src/tethys/deployment/DutyCycleInfo.java index 740b63c9..5bdbe89f 100644 --- a/src/tethys/deployment/DutyCycleInfo.java +++ b/src/tethys/deployment/DutyCycleInfo.java @@ -1,5 +1,7 @@ package tethys.deployment; +import PamUtils.PamCalendar; + public class DutyCycleInfo { public boolean isDutyCycled; @@ -24,7 +26,8 @@ public class DutyCycleInfo { return "No duty cycle"; } else { - return String.format("%3.1fs on, %3.1fs off, for %d cycles", meanOnTimeS, meanGapS, nCycles); + return String.format("%s on, %s off, for %d cycles", PamCalendar.formatDuration((long) (meanOnTimeS*1000)), + PamCalendar.formatDuration((long) (meanGapS*1000)), nCycles); } } diff --git a/src/tethys/detection/DetectionsHandler.java b/src/tethys/detection/DetectionsHandler.java index 11baac0f..e559b752 100644 --- a/src/tethys/detection/DetectionsHandler.java +++ b/src/tethys/detection/DetectionsHandler.java @@ -466,7 +466,7 @@ public class DetectionsHandler { String prefix = deployment.deployment.getId(); detections.setId(String.format("%s_%d", prefix, uniqueDetectionsId++)); // detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams)); - detections.setDescription(exportParams.detectionDescription); + detections.setDescription(exportParams.getNilusDetectionDescription()); DataSourceType dataSource = new DataSourceType(); dataSource.setDeploymentId(deployment.deployment.getId()); // dataSource.setEnsembleId(""); ToDo diff --git a/src/tethys/niluswraps/PDescriptionType.java b/src/tethys/niluswraps/PDescriptionType.java new file mode 100644 index 00000000..889d0684 --- /dev/null +++ b/src/tethys/niluswraps/PDescriptionType.java @@ -0,0 +1,101 @@ +package tethys.niluswraps; + +import java.io.Serializable; + +import nilus.DescriptionType; + +/** + * Because we want to save DescriptionType objects in serialised + * psfx files and because Nilus description types are not serialised + * these have to be wrapped in a total bodge way with reasonably convenient + * constructors and getters for converting back and forth from the nilus object. + * @author dg50 + * + */ +public class PDescriptionType implements Serializable { + + private static final long serialVersionUID = 1L; + + protected String objectives; + + protected String _abstract; + + protected String method; + + /** + * Constructor from a set of strings + * @param objectives + * @param _abstract + * @param method + */ + public PDescriptionType(String objectives, String _abstract, String method) { + super(); + this.objectives = objectives; + this._abstract = _abstract; + this.method = method; + } + + /** + * Construct from a nilus object + * @param descriptionType + */ + public PDescriptionType(DescriptionType descriptionType) { + this.objectives = descriptionType.getObjectives(); + this._abstract = descriptionType.getAbstract(); + this.method = descriptionType.getMethod(); + } + + public PDescriptionType() { + } + + public String getObjectives() { + return objectives; + } + + /** + * @return the _abstract + */ + public String getAbstract() { + return _abstract; + } + + /** + * @param _abstract the _abstract to set + */ + public void setAbstract(String _abstract) { + this._abstract = _abstract; + } + + /** + * @return the method + */ + public String getMethod() { + return method; + } + + /** + * @param method the method to set + */ + public void setMethod(String method) { + this.method = method; + } + + /** + * @param objectives the objectives to set + */ + public void setObjectives(String objectives) { + this.objectives = objectives; + } + + /** + * convert into a nilus object for output. + * @return + */ + public DescriptionType getDescription() { + DescriptionType descriptionType = new DescriptionType(); + descriptionType.setAbstract(_abstract); + descriptionType.setObjectives(objectives); + descriptionType.setMethod(method); + return descriptionType; + } +} diff --git a/src/tethys/output/StreamExportParams.java b/src/tethys/output/StreamExportParams.java index 02e81e2f..2db881fa 100644 --- a/src/tethys/output/StreamExportParams.java +++ b/src/tethys/output/StreamExportParams.java @@ -1,9 +1,11 @@ package tethys.output; +import java.io.IOException; import java.io.Serializable; import nilus.DescriptionType; import nilus.GranularityEnumType; +import tethys.niluswraps.PDescriptionType; /** * Parameters controlling export of a single stream. @@ -32,13 +34,21 @@ public class StreamExportParams implements Serializable { /* * Can't have this here since it isn't serializable. */ - transient public nilus.DescriptionType detectionDescription; + public PDescriptionType detectionDescription; - public DescriptionType getDetectionDescription() { + public PDescriptionType getDetectionDescription() { if (detectionDescription == null) { - detectionDescription = new DescriptionType(); + detectionDescription = new PDescriptionType(); } return detectionDescription; } + + /** + * Get the nilus detection description + * @return + */ + public DescriptionType getNilusDetectionDescription() { + return getDetectionDescription().getDescription(); + } } diff --git a/src/tethys/swing/DeploymentExportPanel.java b/src/tethys/swing/DeploymentExportPanel.java index dd9a7ce0..5a6c6f33 100644 --- a/src/tethys/swing/DeploymentExportPanel.java +++ b/src/tethys/swing/DeploymentExportPanel.java @@ -32,6 +32,7 @@ import nilus.Deployment; import nilus.Deployment.Data; import tethys.TethysControl; import tethys.TethysState; +import tethys.TethysState.StateType; import tethys.dbxml.DBXMLConnect; import tethys.deployment.RecordingPeriod; import tethys.niluswraps.PDeployment; @@ -149,6 +150,10 @@ public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentT case NEWPROJECTSELECTION: updateDeployments(); enableControls(); + break; + case UPDATEMETADATA: + setInternal(); + break; } } @@ -258,6 +263,7 @@ public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentT dbxmlConnect.postToTethys(deployment); } } + getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER)); } private void enableControls() { diff --git a/src/tethys/swing/FancyClientButton.java b/src/tethys/swing/FancyClientButton.java new file mode 100644 index 00000000..3967ae28 --- /dev/null +++ b/src/tethys/swing/FancyClientButton.java @@ -0,0 +1,84 @@ +package tethys.swing; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +import tethys.TethysControl; +import tethys.dbxml.DBXMLConnect; + +/** + * Fancy button which has a normal button AND a drop down + * for other web client pages. + * @author dg50 + * + */ +public class FancyClientButton extends JPanel { + + private JButton clientButton; + private JButton dropButton; + private JPopupMenu collectionsMenu; + private TethysControl tethysControl; + + public FancyClientButton(TethysControl tethysControl) { + this.tethysControl = tethysControl; + setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.ipadx = c.ipady = 0; + c.insets = new Insets(0,0,0,0); + clientButton = new JButton("Open Client"); + clientButton.setToolTipText("Open Tethys web client in default browser"); + dropButton = new JButton("v"); + dropButton.setToolTipText("Open Tethys collections pages in default browser"); + c.gridx = 0; + add(clientButton, c); + c.gridx++; + add(dropButton, c); + + String[] collections = DBXMLConnect.collections; + collectionsMenu = new JPopupMenu(); + for (int i = 0; i < collections.length; i++) { + JMenuItem menuItem = new JMenuItem(collections[i]); + menuItem.addActionListener(new OpenCollection(collections[i])); + collectionsMenu.add(menuItem); + } + + dropButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + collectionsMenu.show(dropButton, 0, 0); + } + }); + } + + public void addActionListener(ActionListener actionListener) { + clientButton.addActionListener(actionListener); + } + + private class OpenCollection implements ActionListener { + + private String collection; + + public OpenCollection(String collection) { + super(); + this.collection = collection; + } + + @Override + public void actionPerformed(ActionEvent e) { + tethysControl.openTethysCollection(collection); + } + + } + + +} diff --git a/src/tethys/swing/PAMGuardDeploymentsTable.java b/src/tethys/swing/PAMGuardDeploymentsTable.java index 7585ce85..74eba98f 100644 --- a/src/tethys/swing/PAMGuardDeploymentsTable.java +++ b/src/tethys/swing/PAMGuardDeploymentsTable.java @@ -2,6 +2,8 @@ package tethys.swing; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; @@ -9,7 +11,9 @@ import java.util.Arrays; import javax.swing.JCheckBox; import javax.swing.JComponent; +import javax.swing.JMenuItem; import javax.swing.JPanel; +import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; @@ -17,10 +21,13 @@ import javax.swing.border.TitledBorder; import javax.swing.table.AbstractTableModel; import PamUtils.PamCalendar; +import PamView.dialog.warn.WarnOnce; import PamView.panel.PamPanel; import PamView.tables.SwingTableColumnWidths; +import nilus.Deployment; import tethys.TethysControl; import tethys.TethysState; +import tethys.TethysState.StateType; import tethys.deployment.DeploymentHandler; import tethys.deployment.DeploymentOverview; import tethys.deployment.RecordingPeriod; @@ -71,14 +78,14 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { @Override public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { - showPopup(); + showPopup(e); } } @Override public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { - showPopup(); + showPopup(e); } } @@ -96,7 +103,7 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { } - public void showPopup() { + public void showPopup(MouseEvent e) { int aRow = table.getSelectedRow(); int[] selRows = table.getSelectedRows(); if (selRows == null || selRows.length == 0) { @@ -111,21 +118,56 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { // make a list of RecordingPeriods which don't currently have a Deployment document ArrayList newPeriods = new ArrayList<>(); ArrayList allPeriods = deploymentOverview.getRecordingPeriods(); + ArrayList matchedDeployments = new ArrayList<>(); for (int i = 0; i < selRows.length; i++) { - if (allPeriods.get(selRows[i]).getMatchedTethysDeployment() == null) { + PDeployment tethysDeployment = allPeriods.get(selRows[i]).getMatchedTethysDeployment(); + if (tethysDeployment == null) { newPeriods.add(allPeriods.get(i)); } + else { + if (matchedDeployments.contains(tethysDeployment) == false) { + matchedDeployments.add(tethysDeployment); + } + } } - if (newPeriods.size() == 0) { - return; + if (matchedDeployments.size() == 1) { + JPopupMenu popMenu = new JPopupMenu(); + JMenuItem menuItem = new JMenuItem("Remove deployment document " + matchedDeployments.get(0)); + menuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + deleteDeployment(matchedDeployments.get(0)); + } + }); + popMenu.add(menuItem); + popMenu.show(e.getComponent(), e.getX(), e.getY()); } - /* - * if we get here, we've one or more rows without a Tethys output, so can have - * a menu to create them. - */ +// if (newPeriods.size() == 0) { +// return; +// } +// /* +// * if we get here, we've one or more rows without a Tethys output, so can have +// * a menu to create them. +// */ + } + protected void deleteDeployment(PDeployment pDeployment) { + Deployment dep = pDeployment.deployment; + if (dep == null) { + return; + } + int ans = WarnOnce.showWarning(getTethysControl().getGuiFrame(), "Delete Deployment document", + "Are you sure you want to delete the deployment document " + dep.getId(), WarnOnce.OK_CANCEL_OPTION); + if (ans == WarnOnce.CANCEL_OPTION) { + return; + } + boolean gone = getTethysControl().getDbxmlConnect().deleteDocument(dep); + getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER)); + } + /** * Get a list of selected recording periods. * @return list of selected periods. @@ -172,6 +214,9 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { private void updateDeployments() { DeploymentHandler deploymentHandler = getTethysControl().getDeploymentHandler(); deploymentOverview = deploymentHandler.getDeploymentOverview(); + if (deploymentOverview == null) { + return; + } int n = deploymentOverview.getRecordingPeriods().size(); if (selection.length < n) { selection = Arrays.copyOf(selection, n); diff --git a/src/tethys/swing/TethysConnectionPanel.java b/src/tethys/swing/TethysConnectionPanel.java index 95837d6a..23c531dd 100644 --- a/src/tethys/swing/TethysConnectionPanel.java +++ b/src/tethys/swing/TethysConnectionPanel.java @@ -62,7 +62,7 @@ public class TethysConnectionPanel extends TethysGUIPanel { private JButton newInstrument; - private JButton openClient; + private FancyClientButton openClient; public TethysConnectionPanel(TethysControl tethysControl) { super(tethysControl); @@ -73,8 +73,8 @@ public class TethysConnectionPanel extends TethysGUIPanel { serverSelButton.setToolTipText("Select server"); serverStatus = new ScrollingPamLabel(SERVERSTATUSLENGTH); serverName.setEditable(false); - openClient = new JButton("Open Client"); - openClient.setToolTipText("Open Tethys client in web browser"); + openClient = new FancyClientButton(tethysControl); +// openClient.setToolTipText("Open Tethys client in web browser"); // serverStatus.setEditable(false); serverSelButton.addActionListener(new ActionListener() { @Override diff --git a/src/tethys/swing/export/DescriptionTypePanel.java b/src/tethys/swing/export/DescriptionTypePanel.java index 2fc968cb..ffa75651 100644 --- a/src/tethys/swing/export/DescriptionTypePanel.java +++ b/src/tethys/swing/export/DescriptionTypePanel.java @@ -12,6 +12,7 @@ import javax.swing.border.TitledBorder; import PamView.dialog.PamDialog; import nilus.DescriptionType; +import tethys.niluswraps.PDescriptionType; /** * Panel containing the three test entry fields for nilus.DescriptionType @@ -65,7 +66,7 @@ public class DescriptionTypePanel { return mainPanel; } - public void setParams(DescriptionType description) { + public void setParams(PDescriptionType description) { if (description == null) { tObjectives.setText(null); tAbstract.setText(null); @@ -73,7 +74,7 @@ public class DescriptionTypePanel { } } - public boolean getParams(DescriptionType description) { + public boolean getParams(PDescriptionType description) { if (checkField(requireObjective, tObjectives) == false) { return PamDialog.showWarning(null, "Objectives", "The objectives field must be competed"); }