diff --git a/src/PamController/PamSensor.java b/src/PamController/PamSensor.java new file mode 100644 index 00000000..03e51efe --- /dev/null +++ b/src/PamController/PamSensor.java @@ -0,0 +1,20 @@ +package PamController; + +/** + * Interface to define modules which can be considered as sensors of some sort. + * e.g. depth and orientation modules and the SoundTrap clickdetecotr + * @author dg50 + * + */ +public interface PamSensor { + + public String getUnitName(); + + public String getUnitType(); + + public String getSensorDescription(); + + public String getSensorId(); + + +} diff --git a/src/PamUtils/PamCalendar.java b/src/PamUtils/PamCalendar.java index d41aa018..7c4c3eb8 100644 --- a/src/PamUtils/PamCalendar.java +++ b/src/PamUtils/PamCalendar.java @@ -47,7 +47,7 @@ public class PamCalendar { public static TimeZone defaultTimeZone = TimeZone.getTimeZone("UTC"); - private static TimeZone localTimeZone = TimeZone.getDefault(); + private static TimeZone localTimeZone = defaultTimeZone;// TimeZone.getDefault(); public static final long millisPerDay = 1000L*24L*3600L; diff --git a/src/dataMap/DataStreamPanel.java b/src/dataMap/DataStreamPanel.java index 957eadfd..aaa743e3 100644 --- a/src/dataMap/DataStreamPanel.java +++ b/src/dataMap/DataStreamPanel.java @@ -747,9 +747,9 @@ public class DataStreamPanel extends JPanel implements DataMapObserver { String tipText; if (startTimeArrow != null && startTimeArrow.contains(me.getPoint())) { - tipText = "Data Start: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataStart(), true); + tipText = "Data Start: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataStart(), false); } else if (endTimeArrow != null && endTimeArrow.contains(me.getPoint())) { - tipText = "Data End: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataEnd(), true); + tipText = "Data End: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataEnd(), false); } else { tipText = "Cursor: " + PamCalendar.formatDateTime(tm, true); } diff --git a/src/soundtrap/STClickControl.java b/src/soundtrap/STClickControl.java index f210c765..4457f4e7 100644 --- a/src/soundtrap/STClickControl.java +++ b/src/soundtrap/STClickControl.java @@ -37,6 +37,7 @@ import javax.swing.JSeparator; import org.pamguard.x3.sud.SUDClickDetectorInfo; import Acquisition.AcquisitionControl; +import PamController.PamSensor; import PamController.PamControlledUnitSettings; import PamController.PamController; import PamguardMVC.PamRawDataBlock; @@ -51,7 +52,7 @@ import soundtrap.sud.SudFileDWVHandler; * @author mo55 * */ -public class STClickControl extends ClickControl { +public class STClickControl extends ClickControl implements PamSensor { private SUDClickDetectorInfo sudClickDetectorInfo; @@ -217,6 +218,17 @@ public class STClickControl extends ClickControl { public void setSudClickDetectorInfo(SUDClickDetectorInfo sudClickDetectorInfo) { this.sudClickDetectorInfo = sudClickDetectorInfo; } + + @Override + public String getSensorDescription() { + String desc = String.format("SoundTrap Click Detector at %dHz", (int) getClickDataBlock().getSampleRate()); + return desc; + } + + @Override + public String getSensorId() { + return null; + } } diff --git a/src/tethys/dbxml/DBXMLQueries.java b/src/tethys/dbxml/DBXMLQueries.java index f906badd..40190546 100644 --- a/src/tethys/dbxml/DBXMLQueries.java +++ b/src/tethys/dbxml/DBXMLQueries.java @@ -264,6 +264,9 @@ public class DBXMLQueries { e.printStackTrace(); return null; } + if (doc == null) { + return null; + } ArrayList detectionsNames = new ArrayList(); int count = 0; NodeList returns = doc.getElementsByTagName("Detections"); diff --git a/src/tethys/deployment/DeploymentHandler.java b/src/tethys/deployment/DeploymentHandler.java index a87f8d30..42b87035 100644 --- a/src/tethys/deployment/DeploymentHandler.java +++ b/src/tethys/deployment/DeploymentHandler.java @@ -15,21 +15,24 @@ import Acquisition.AcquisitionControl; import Acquisition.AcquisitionParameters; import Acquisition.DaqStatusDataUnit; import Acquisition.DaqSystem; +import Acquisition.FolderInputSystem; import Array.ArrayManager; import Array.Hydrophone; import Array.HydrophoneLocator; import Array.PamArray; import Array.Streamer; import Array.ThreadingHydrophoneLocator; +import PamController.PamSensor; import PamController.PamControlledUnit; import PamController.PamController; import PamUtils.LatLong; -import PamUtils.PamCalendar; import PamUtils.PamUtils; import PamguardMVC.PamDataBlock; -import SoundRecorder.RecordingInfo; -import javafx.scene.chart.PieChart.Data; -import metadata.MetaDataContol; +import PamguardMVC.PamRawDataBlock; +import binaryFileStorage.BinaryStore; +import dataMap.OfflineDataMap; +import dataMap.OfflineDataMapPoint; +import generalDatabase.DBControlUnit; import metadata.deployment.DeploymentData; import nilus.Audio; import nilus.ChannelInfo; @@ -39,12 +42,14 @@ import nilus.ChannelInfo.DutyCycle.Regimen.RecordingIntervalS; import nilus.ChannelInfo.Sampling; import nilus.ChannelInfo.Sampling.Regimen; import nilus.Deployment; +import nilus.Deployment.Data; import nilus.Deployment.Instrument; import nilus.Deployment.SamplingDetails; import nilus.Deployment.Sensors; import nilus.DeploymentRecoveryDetails; import nilus.GeometryTypeM; import nilus.Helper; +import nilus.UnknownSensor; import pamMaths.PamVector; import pamMaths.STD; import tethys.TethysControl; @@ -52,7 +57,10 @@ import tethys.TethysLocationFuncs; import tethys.TethysState; import tethys.TethysStateObserver; import tethys.TethysTimeFuncs; +import tethys.TethysState.StateType; +import tethys.dbxml.DBXMLConnect; import tethys.niluswraps.PDeployment; +import tethys.output.TethysExportParams; /** * Functions to gather data for the deployment document from all around PAMGuard. @@ -66,6 +74,13 @@ public class DeploymentHandler implements TethysStateObserver { private TethysControl tethysControl; + /** + * @return the tethysControl + */ + public TethysControl getTethysControl() { + return tethysControl; + } + private DeploymentOverview deploymentOverview; private ArrayList projectDeployments; @@ -184,6 +199,10 @@ public class DeploymentHandler implements TethysStateObserver { else { tempPeriods = extractTimesFromStatus(allStatusData); } + 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."); + tempPeriods = extractTimesFromOutputMaps(); + } 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; @@ -255,6 +274,123 @@ public class DeploymentHandler implements TethysStateObserver { } + /** + * Exprt deployments docs. Playing with a couple of different ways of doing this. + * @param selectedDeployments + */ + public void exportDeployments(ArrayList selectedDeployments) { + if (false) { + exportSeparateDeployments(selectedDeployments); + } + else { + exportOneDeploymnet(selectedDeployments); + } + + } + /** + * Make one big deployment document with all the recording periods in it. + */ + private void exportOneDeploymnet(ArrayList selectedDeployments) { + // do the lot, whatever ... + selectedDeployments = getDeploymentOverview().getRecordingPeriods(); + int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId(); + RecordingPeriod onePeriod = new RecordingPeriod(selectedDeployments.get(freeId).getRecordStart(), + selectedDeployments.get(selectedDeployments.size()-1).getRecordStop()); + Deployment deployment = createDeploymentDocument(freeId, onePeriod); + // fill in a few things from here + DeploymentData globalMeta = getTethysControl().getGlobalDeplopymentData(); + deployment.setCruise(globalMeta.getCruise()); + deployment.setSite(globalMeta.getSite()); + if (selectedDeployments.size() > 1) { + // now need to remove the + SamplingDetails samplingDetails = deployment.getSamplingDetails(); + samplingDetails.getChannel().clear(); + for (int i = 0; i < selectedDeployments.size(); i++) { + addSamplingDetails(deployment, selectedDeployments.get(i)); + } + } + DBXMLConnect dbxmlConnect = getTethysControl().getDbxmlConnect(); + PDeployment exDeploymnet = onePeriod.getMatchedTethysDeployment(); + if (exDeploymnet != null) { + deployment.setId(exDeploymnet.deployment.getId()); + dbxmlConnect.updateDocument(deployment); + } + else { + dbxmlConnect.postToTethys(deployment); + } + getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER)); + } + + /** + * Make a separate deployment document for every recording period. + */ + private void exportSeparateDeployments(ArrayList selectedDeployments) { + + int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId(); + for (int i = 0; i < selectedDeployments.size(); i++) { + RecordingPeriod recordPeriod = selectedDeployments.get(i); + PDeployment exDeploymnet = recordPeriod.getMatchedTethysDeployment(); + Deployment deployment = null; + if (exDeploymnet != null) { + deployment = createDeploymentDocument(freeId, recordPeriod); + deployment.setId(exDeploymnet.deployment.getId()); + } + if (deployment == null) { + deployment = createDeploymentDocument(freeId++, recordPeriod); + } + // fill in a few things from here + DeploymentData globalMeta = getTethysControl().getGlobalDeplopymentData(); + deployment.setCruise(globalMeta.getCruise()); + deployment.setSite(globalMeta.getSite()); + // also need to sort out track data here, etc. + DBXMLConnect dbxmlConnect = getTethysControl().getDbxmlConnect(); + if (exDeploymnet != null) { + dbxmlConnect.updateDocument(deployment); + } + else { + dbxmlConnect.postToTethys(deployment); + } + } + getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER)); + } + + /** + * Get data times from any other datamap, since this will generally match the acquisition anyway + * @return + */ + private ArrayList extractTimesFromOutputMaps() { + OfflineDataMap bestMap = null; + PamDataBlock bestBlock = null; + long firstStart = Long.MAX_VALUE; + long lastEnd = Long.MIN_VALUE; + ArrayList dataBlocks = PamController.getInstance().getDetectorDataBlocks(); + for (PamDataBlock aBlock : dataBlocks) { + if (aBlock instanceof PamRawDataBlock) { + continue; // don't want acquisition ! + } + OfflineDataMap dataMap = aBlock.getPrimaryDataMap(); + if (dataMap == null) { + continue; + } + if (dataMap.getFirstDataTime() < firstStart && dataMap.getLastDataTime() > lastEnd) { + bestMap = dataMap; + bestBlock = aBlock; + firstStart = dataMap.getFirstDataTime(); + lastEnd = dataMap.getLastDataTime(); + } + } + if (bestMap == null) { + return null; + } + // get the times out of it. + ArrayList recPeriods = new ArrayList<>(); + List mapPoints = bestMap.getMapPoints(); + for (OfflineDataMapPoint mapPoint : mapPoints) { + recPeriods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime())); + } + return recPeriods; + } + public DeploymentOverview getDeploymentOverview() { return deploymentOverview; } @@ -305,7 +441,7 @@ public class DeploymentHandler implements TethysStateObserver { * @return overlap in milliseconds */ public long getDeploymentOverlap(PDeployment aDeployment, RecordingPeriod aPeriod) { - long start = aPeriod.getRecordStart(); + long start = aPeriod.getRecordStart(); // recording period. long stop = aPeriod.getRecordStop(); long depStart = aDeployment.getAudioStart(); long depStop = aDeployment.getAudioEnd(); @@ -551,7 +687,8 @@ public class DeploymentHandler implements TethysStateObserver { e.printStackTrace(); } DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData(); - String id = String.format("%s_%d", globalDeplData.getProject(), i); + TethysExportParams exportParams = tethysControl.getTethysExportParams(); + String id = String.format("%s_%d", exportParams.getDatasetName(), i); deployment.setId(id); deployment.setDeploymentId(i); @@ -576,9 +713,11 @@ public class DeploymentHandler implements TethysStateObserver { getProjectData(deployment); - getSamplingDetails(deployment, recordingPeriod); + addSamplingDetails(deployment, recordingPeriod); getSensorDetails(deployment); + + getSensors(deployment); /** * Stuff that may need to be put into the UI: @@ -586,12 +725,101 @@ public class DeploymentHandler implements TethysStateObserver { * this may be for the export UI ? * Tracks: trackline information. General problem in PAMGUard. */ - + getDataDetails(deployment); return deployment; } + public String getBinaryDataURI() { + BinaryStore binStore = BinaryStore.findBinaryStoreControl(); + if (binStore != null) { + return binStore.getBinaryStoreSettings().getStoreLocation(); + } + return null; + } + + public String getDatabaseURI() { + DBControlUnit databaseControl = DBControlUnit.findDatabaseControl(); + if (databaseControl != null) { + return databaseControl.getLongDatabaseName(); + } + return null; + } + + public String getRawDataURI() { + try { + PamControlledUnit daq = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); + if (daq instanceof AcquisitionControl) { + AcquisitionControl daqCtrl = (AcquisitionControl) daq; + DaqSystem system = daqCtrl.findDaqSystem(null);// getAcquisitionProcess().getRunningSystem(); + if (system instanceof FolderInputSystem) { + FolderInputSystem fip = (FolderInputSystem) system; + return fip.getFolderInputParameters().recentFiles.get(0); + } + } + } + catch (Exception e) { + } + return "unknown"; + } + + private void getDataDetails(Deployment deployment) { + Data data = deployment.getData(); + if (data == null) { + data = new Data(); + deployment.setData(data); + } + nilus.Deployment.Data.Audio audio = data.getAudio(); + if (audio == null) { + audio = new nilus.Deployment.Data.Audio(); + data.setAudio(audio); + } + audio.setURI(getRawDataURI()); + String processed = "Database:"+getDatabaseURI(); + String binary = getBinaryDataURI(); + if (binary != null) { + binary += ";Binary:"+binary; + } + audio.setProcessed(processed); + + } + + /** + * Get sensor information. The Soundtrap CTD will count as a sensor. + * Modules that are sensors will have to implement a PAMSensor interface + * @param deployment + */ + private void getSensors(Deployment deployment) { + ArrayList sensorModules = PamController.getInstance().findControlledUnits(PamSensor.class, true); + if (sensorModules == null || sensorModules.size() == 0) { + return; + } + Sensors sensors = deployment.getSensors(); + if (sensors == null) { + sensors = new Sensors(); + deployment.setSensors(sensors); + } + List sensorList = sensors.getSensor(); + for (PamControlledUnit aUnit : sensorModules) { + PamSensor pamSensor = (PamSensor) aUnit; + UnknownSensor nilusSensor = new UnknownSensor(); + try { + Helper.createRequiredElements(nilusSensor); + } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } +// nilusSensor.setName(pamSensor.getUnitName()); + nilusSensor.setType(pamSensor.getUnitType()); + nilusSensor.setNumber(BigInteger.ZERO); + nilusSensor.setDescription(pamSensor.getSensorDescription()); + nilusSensor.setSensorId(pamSensor.getUnitType()); + + sensorList.add(nilusSensor); + } + } + /** * Add project Metadata to a Deploymnet document. This is currently being * made available in the MetaDataControl module which should be added to PAMGuard @@ -781,10 +1009,18 @@ public class DeploymentHandler implements TethysStateObserver { * @param deployment * @param recordingPeriod */ - private boolean getSamplingDetails(Deployment deployment, RecordingPeriod recordingPeriod) { - SamplingDetails samplingDetails = new SamplingDetails(); + private boolean addSamplingDetails(Deployment deployment, RecordingPeriod recordingPeriod) { + + SamplingDetails samplingDetails = deployment.getSamplingDetails(); + if (samplingDetails == null) { + samplingDetails = new SamplingDetails(); + deployment.setSamplingDetails(samplingDetails); + } // this is basically going to be a list of almost identical channel information // currently just for the first acquisition. May extend to more. + // see if there is > 1 acquisition. May want to include many. + ArrayList daqUnits = PamController.getInstance().findControlledUnits(AcquisitionControl.class); + AcquisitionControl daq = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); if (daq == null) { return false; @@ -858,7 +1094,6 @@ public class DeploymentHandler implements TethysStateObserver { * earlier to a wrapper around the Deployment class. */ } - deployment.setSamplingDetails(samplingDetails); return true; } diff --git a/src/tethys/output/TethysExportParams.java b/src/tethys/output/TethysExportParams.java index 7172b6cc..81ad0eb3 100644 --- a/src/tethys/output/TethysExportParams.java +++ b/src/tethys/output/TethysExportParams.java @@ -3,6 +3,7 @@ package tethys.output; import java.io.Serializable; import java.util.HashMap; import PamguardMVC.PamDataBlock; +import generalDatabase.DBControlUnit; import metadata.deployment.DeploymentData; @@ -30,6 +31,51 @@ public class TethysExportParams implements Serializable, Cloneable{ private HashMap streamParamsMap = new HashMap(); private DeploymentData deploymentData; + + /** + * PAMGuard HAS to have a dataset name to link to data in Tethys, or it all gets + * very confusing. This will be used in Deployment and Detection document names. + */ + private String datasetName; + + /** + * @return the datasetName + */ + public String getDatasetName() { + if (datasetName == null) { + datasetName = getDefaultDatasetName(); + } + return datasetName; + } + + private String getDefaultDatasetName() { + // get the database name. It must exist in viewer mode ! + DBControlUnit dbControl = DBControlUnit.findDatabaseControl(); + String dbName = dbControl.getDatabaseName(); + // strip off trailing file type. + int dPos = dbName.lastIndexOf('.'); + if (dPos > 0) { + dbName = dbName.substring(0, dPos); + } + /* + * if the name ends in database, then remove that too (this is quite + * common since it's the default for batch output + */ + if (dbName.toLowerCase().endsWith("database")) { + dbName = dbName.substring(0, dbName.length()-"database".length()); + } + if (dbName.endsWith("_")) { + dbName = dbName.substring(0, dbName.length()-1); + } + return dbName; + } + + /** + * @param datasetName the datasetName to set + */ + public void setDatasetName(String datasetName) { + this.datasetName = datasetName; + } @Override public TethysExportParams clone() { diff --git a/src/tethys/swing/DeploymentExportPanel.java b/src/tethys/swing/DeploymentExportPanel.java index 5a6c6f33..2c2c6332 100644 --- a/src/tethys/swing/DeploymentExportPanel.java +++ b/src/tethys/swing/DeploymentExportPanel.java @@ -34,6 +34,7 @@ import tethys.TethysControl; import tethys.TethysState; import tethys.TethysState.StateType; import tethys.dbxml.DBXMLConnect; +import tethys.deployment.DeploymentHandler; import tethys.deployment.RecordingPeriod; import tethys.niluswraps.PDeployment; @@ -94,7 +95,7 @@ public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentT addPair("Cruise ", cruise, c); addPair("Raw data URI ", rawURI, c); addPair("Binary data URI ", binaryURI, c); - addPair("Datbase URI ", databaseURI, c); + addPair("Database URI ", databaseURI, c); addPair("Contact ", contact, c); addPair("Date ", date, c); addPair("Set from ", projectDeployments, c); @@ -197,31 +198,35 @@ public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentT private void setDefaultStores() { + DeploymentHandler deploymentHandler = getTethysControl().getDeploymentHandler(); + binaryURI.setText(deploymentHandler.getBinaryDataURI()); + databaseURI.setText(deploymentHandler.getDatabaseURI()); + rawURI.setText(deploymentHandler.getRawDataURI()); - BinaryStore binStore = BinaryStore.findBinaryStoreControl(); - if (binStore != null) { - binaryURI.setText(binStore.getBinaryStoreSettings().getStoreLocation()); - } - - DBControlUnit databaseControl = DBControlUnit.findDatabaseControl(); - if (databaseControl != null) { - databaseURI.setText(databaseControl.getLongDatabaseName()); - } - - try { - PamControlledUnit daq = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); - if (daq instanceof AcquisitionControl) { - AcquisitionControl daqCtrl = (AcquisitionControl) daq; - DaqSystem system = daqCtrl.findDaqSystem(null);// getAcquisitionProcess().getRunningSystem(); - if (system instanceof FolderInputSystem) { - FolderInputSystem fip = (FolderInputSystem) system; - rawURI.setText(fip.getFolderInputParameters().recentFiles.get(0)); - } - } - } - catch (Exception e) { - rawURI.setText("unknown"); - } +// BinaryStore binStore = BinaryStore.findBinaryStoreControl(); +// if (binStore != null) { +// binaryURI.setText(binStore.getBinaryStoreSettings().getStoreLocation()); +// } +// +// DBControlUnit databaseControl = DBControlUnit.findDatabaseControl(); +// if (databaseControl != null) { +// databaseURI.setText(databaseControl.getLongDatabaseName()); +// } +// +// try { +// PamControlledUnit daq = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); +// if (daq instanceof AcquisitionControl) { +// AcquisitionControl daqCtrl = (AcquisitionControl) daq; +// DaqSystem system = daqCtrl.findDaqSystem(null);// getAcquisitionProcess().getRunningSystem(); +// if (system instanceof FolderInputSystem) { +// FolderInputSystem fip = (FolderInputSystem) system; +// rawURI.setText(fip.getFolderInputParameters().recentFiles.get(0)); +// } +// } +// } +// catch (Exception e) { +// rawURI.setText("unknown"); +// } } @@ -235,36 +240,9 @@ public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentT if (selectedDeployments == null || selectedDeployments.size() == 0) { return; }; - int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId(); - for (int i = 0; i < selectedDeployments.size(); i++) { - RecordingPeriod recordPeriod = selectedDeployments.get(i); - PDeployment exDeploymnet = recordPeriod.getMatchedTethysDeployment(); - Deployment deployment = null; - if (exDeploymnet != null) { - deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId, recordPeriod); - deployment.setId(exDeploymnet.deployment.getId()); - } - if (deployment == null) { - deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId++, recordPeriod); - } - // fill in a few things from here - deployment.setCruise(cruise.getText()); - deployment.setSite(site.getText()); - // also need to sort out track data here, etc. -// Should really tidy this up a lot and move functionality to DeploymentHandler with all -// the metadata in a object ? -// Data data = new nilus.Deployment.Data(); -// d - DBXMLConnect dbxmlConnect = getTethysControl().getDbxmlConnect(); - if (exDeploymnet != null) { - dbxmlConnect.updateDocument(deployment); - } - else { - dbxmlConnect.postToTethys(deployment); - } - } - getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER)); + getTethysControl().getDeploymentHandler().exportDeployments(selectedDeployments); } + private void enableControls() { boolean enable = selectedDeployments != null && selectedDeployments.size() > 0; diff --git a/src/tethys/swing/FancyClientButton.java b/src/tethys/swing/FancyClientButton.java index 3967ae28..deb9a8b4 100644 --- a/src/tethys/swing/FancyClientButton.java +++ b/src/tethys/swing/FancyClientButton.java @@ -1,6 +1,7 @@ package tethys.swing; import java.awt.BorderLayout; +import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -8,10 +9,12 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BoxLayout; +import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import javax.swing.border.EmptyBorder; import tethys.TethysControl; import tethys.dbxml.DBXMLConnect; @@ -32,17 +35,36 @@ public class FancyClientButton extends JPanel { public FancyClientButton(TethysControl tethysControl) { this.tethysControl = tethysControl; setLayout(new GridBagLayout()); +// setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); GridBagConstraints c = new GridBagConstraints(); c.ipadx = c.ipady = 0; c.insets = new Insets(0,0,0,0); + c.fill = GridBagConstraints.VERTICAL; clientButton = new JButton("Open Client"); clientButton.setToolTipText("Open Tethys web client in default browser"); - dropButton = new JButton("v"); + ImageIcon arrowDown= null; + try { + arrowDown = new ImageIcon(ClassLoader + .getSystemResource("Resources/SidePanelShowH.png")); + } + catch (Exception e) { + } + if (arrowDown != null) { + dropButton = new JButton(arrowDown); + } + else { + dropButton = new JButton("v"); + } dropButton.setToolTipText("Open Tethys collections pages in default browser"); c.gridx = 0; add(clientButton, c); c.gridx++; add(dropButton, c); + Insets dInsets = dropButton.getInsets(); + if (dInsets != null) { + dInsets.left = dInsets.right = 4; + dropButton.setBorder(new EmptyBorder(dInsets)); + } String[] collections = DBXMLConnect.collections; collectionsMenu = new JPopupMenu();