effortBlocks = new ArrayList();
+ for (PamDataBlock aBlock : allBlocks) {
+ if (aBlock.getEffortProvider() != null) {
+ effortBlocks.add(aBlock);
+ }
+ }
+ return effortBlocks;
+ }
+
+ private PamController getPamController() {
+ return PamController.getInstance();
+ }
+}
diff --git a/src/effort/EffortProvider.java b/src/effort/EffortProvider.java
new file mode 100644
index 00000000..6da999c2
--- /dev/null
+++ b/src/effort/EffortProvider.java
@@ -0,0 +1,192 @@
+package effort;
+
+import java.awt.Frame;
+import java.awt.Window;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import Map.MapParametersDialog;
+import PamController.PamController;
+import PamView.GeneralProjector;
+import PamView.PamSymbol;
+import PamView.symbol.PamSymbolChooser;
+import PamView.symbol.PamSymbolManager;
+import PamView.symbol.SwingSymbolOptionsPanel;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import PamguardMVC.dataSelector.DataSelectDialog;
+import PamguardMVC.dataSelector.DataSelector;
+
+/**
+ * Set of functions that can be returned from any datablock which can
+ * give information about effort. For detectors with binary storage, they
+ * will return a standard binary store effort provider. Others, e.g.
+ * logger forms, acquisition, etc. can so something much more bespoke.
+ * For real time, will need quite different behaviour to offline. Datablocks
+ * with a effortProvider are going to notify this and a local list will be
+ * kept of starts and ends for the entire operation period. This will be
+ * overridden for differeing offline scenarios and bespoke cases such as
+ * logger forms (so need to get a notification in here for every data unit too !)
+ * @author dg50
+ *
+ */
+public abstract class EffortProvider {
+
+ private PamDataBlock parentDataBlock;
+ private boolean isViewer;
+
+ public EffortProvider(PamDataBlock parentDataBlock) {
+ super();
+ this.parentDataBlock = parentDataBlock;
+ this.isViewer = PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW;
+ }
+
+ /**
+ * Notified at real time start.
+ * @param timeMilliseconds
+ */
+ public abstract void realTimeStart(long timeMilliseconds);
+
+ /**
+ * notified at real time end
+ * @param timeMilliseconds
+ */
+ public abstract void realTimeStop(long timeMilliseconds); ;
+
+ /**
+ * Notified for real time data.
+ * @param pamDataUnit
+ */
+ public abstract void newData(PamDataUnit pamDataUnit); ;
+
+ /**
+ * Get the effort for a specific time.
+ * @param timeMilliseconds
+ * @return Effort thing. Can be null if off effort.
+ */
+ public EffortDataUnit getEffort(long timeMilliseconds) {
+ List allEfforts = getAllEffortThings();
+ if (allEfforts == null) {
+ return null;
+ }
+ Iterator it = allEfforts.iterator();
+ while (it.hasNext()) {
+ EffortDataUnit next = it.next();
+ if (timeMilliseconds >= next.getEffortStart() && timeMilliseconds <= next.getEffortEnd()) {
+ return next;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Called when viewer data have been loaded for the parent datablock.
+ */
+ public abstract void viewerLoadData();
+
+ /**
+ * Get all effort things. e.g. for binary data this is more or less a copy of
+ * the datamap (perhaps new units without the gaps).
+ * @return
+ */
+ public abstract List getAllEffortThings();
+
+ /**
+ * @return the parentDataBlock
+ */
+ public PamDataBlock getParentDataBlock() {
+ return parentDataBlock;
+ }
+
+ /**
+ * Get a data selector. For specialist effort modules, this will probably call
+ * through to the datablocks data selection system. Others, such as binaryEffortProvider
+ * can return null since they are either on or off.
+ * @param selectorName
+ * @return
+ */
+ public abstract DataSelector getDataSelector(String selectorName);
+
+ /**
+ * Get the name of this effort provider.
+ */
+ public abstract String getName();
+
+ /**
+ * Get a symbol manager. For specialist effort modules, this will probably call
+ * through to the datablocks existing symbol management system. Others, such as binaryEffortProvider
+ * will need a chooser for the simple on/off data types. .
+ * @return
+ */
+ public abstract PamSymbolManager getSymbolManager();
+
+ public PamSymbolChooser getSymbolChooser(String chooserName, GeneralProjector projector) {
+ PamSymbolManager symbolManager = getSymbolManager();
+ if (symbolManager == null) {
+ return null;
+ }
+ return symbolManager.getSymbolChooser(chooserName, projector);
+ }
+
+ public PamSymbol getPamSymbol(String symbolChooserName, PamDataUnit dataUnit, GeneralProjector projector) {
+ PamSymbolChooser chooser = getSymbolChooser(symbolChooserName, projector);
+ return getPamSymbol(chooser, dataUnit);
+ }
+
+ /**
+ * Need to use this to get symbols for effort instead of direct calls into
+ * the symbol chooser, since the symbol chooser will almost definitely want
+ * it's own type of data unit, NOT the EffortDataUnit which will probably crash
+ * due to a cast exception.
+ * @param chooser
+ * @param dataUnit
+ * @return
+ */
+ public PamSymbol getPamSymbol(PamSymbolChooser chooser, PamDataUnit dataUnit) {
+ if (chooser == null) {
+ return null;
+ }
+ // possible that the data is an Effort unit that wraps a real data unit. Need to
+ // probably pass the original.
+ if (dataUnit instanceof EffortDataUnit) {
+ PamDataUnit refData = ((EffortDataUnit) dataUnit).getReferenceDataUnit();
+ if (refData != null) {
+ dataUnit = refData;
+ }
+ }
+
+ return chooser.getPamSymbol(chooser.getProjector(), dataUnit);
+ }
+
+ public boolean showOptionsDialog(Window parent, String observerName) {
+ PamSymbolChooser symbolChooser = getSymbolChooser(observerName, null);
+ if (symbolChooser == null) {
+ return false;
+ }
+ SwingSymbolOptionsPanel panel = symbolChooser.getSwingOptionsPanel(null);
+ if (panel == null) {
+ return false;
+ }
+ DataSelectDialog dataSelectDialog = new DataSelectDialog(parent, parentDataBlock, null, symbolChooser);
+ boolean ans = dataSelectDialog.showDialog();
+
+ return ans;
+ }
+
+ /**
+ * @return the isViewer
+ */
+ public boolean isViewer() {
+ return isViewer;
+ }
+
+ public EffortDataUnit getLastEffort() {
+ List all = getAllEffortThings();
+ if (all == null || all.size() == 0) {
+ return null;
+ }
+ return all.get(all.size()-1);
+ }
+
+}
diff --git a/src/effort/binary/DataMapEffortProvider.java b/src/effort/binary/DataMapEffortProvider.java
new file mode 100644
index 00000000..11d27047
--- /dev/null
+++ b/src/effort/binary/DataMapEffortProvider.java
@@ -0,0 +1,158 @@
+package effort.binary;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import PamController.OfflineDataStore;
+import PamController.PamController;
+import PamView.symbol.PamSymbolManager;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import PamguardMVC.dataSelector.DataSelector;
+import binaryFileStorage.BinaryStore;
+import dataMap.OfflineDataMap;
+import dataMap.OfflineDataMapPoint;
+import effort.EffortDataUnit;
+import effort.EffortProvider;
+
+/**
+ * Effort provider for most types of datablock that bases itself off one of the
+ * datamaps, binary (preferred) or database. Binary better since database doesn't really
+ * have proper effort data for most blocks.
+ * However, we want this to work online too, so will need to have quite different functionality
+ * for real time and viewer operations.
+ * @author dg50
+ *
+ */
+public class DataMapEffortProvider extends EffortProvider {
+
+ private DataMapSymbolManager binarySymbolManager;
+
+ private Class> dataStoreClass;
+
+ private long maxGap = 0;
+
+ private ArrayList allEfforts;
+
+ /**
+ *
+ * @param parentDataBlock
+ * @param dataStoreClass
+ * @param maxGapMillis
+ */
+ public DataMapEffortProvider(PamDataBlock parentDataBlock, Class> dataStoreClass, long maxGapMillis) {
+ super(parentDataBlock);
+ this.dataStoreClass = dataStoreClass;
+ this.maxGap = maxGapMillis;
+ binarySymbolManager = new DataMapSymbolManager(parentDataBlock);
+ }
+
+ /**
+ *
+ * @param parentDataBlock
+ * @param dataStoreClass
+ */
+ public DataMapEffortProvider(PamDataBlock parentDataBlock, Class dataStoreClass) {
+ this(parentDataBlock, dataStoreClass, 0);
+ }
+
+ @Override
+ public String getName() {
+ return getParentDataBlock().getDataName();
+ }
+
+// @Override
+// public EffortDataUnit getEffort(long timeMilliseconds) {
+// OfflineDataMap dataMap = findDataMap();
+// if (dataMap == null) {
+// return null;
+// }
+// OfflineDataMapPoint foundPt = dataMap.findMapPoint(timeMilliseconds);
+// if (foundPt != null) {
+// return new DataMapEffortThing(this, getParentDataBlock(), foundPt.getStartTime(), foundPt.getEndTime());
+// }
+// return null;
+// }
+
+ @Override
+ public List getAllEffortThings() {
+ return allEfforts;
+ }
+
+ private OfflineDataMap findDataMap() {
+ if (dataStoreClass == null) {
+ return getParentDataBlock().getPrimaryDataMap();
+ }
+ try {
+ OfflineDataStore dataStore = (OfflineDataStore) PamController.getInstance().findControlledUnit(dataStoreClass, null);
+ if (dataStore != null) {
+ return getParentDataBlock().getOfflineDataMap(dataStore);
+ }
+ }
+ catch (Exception e) {
+ }
+ return null;
+ }
+
+ @Override
+ public DataSelector getDataSelector(String selectorName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public PamSymbolManager getSymbolManager() {
+ return binarySymbolManager;
+ }
+
+ @Override
+ public void realTimeStart(long timeMilliseconds) {
+ if (allEfforts == null) {
+ allEfforts = new ArrayList<>();
+ }
+ EffortDataUnit newEffort = new EffortDataUnit(this, null, timeMilliseconds, EffortDataUnit.ONGOINGEFFORT);
+ allEfforts.add(newEffort);
+ }
+
+ @Override
+ public void realTimeStop(long timeMilliseconds) {
+ if (allEfforts == null || allEfforts.size() == 0) {
+ return;
+ }
+ EffortDataUnit lastEff = allEfforts.get(allEfforts.size()-1);
+ lastEff.setEffortEnd(timeMilliseconds);
+
+ }
+
+ @Override
+ public void newData(PamDataUnit pamDataUnit) {
+ // do nothing for individual data units.
+ }
+
+ @Override
+ public void viewerLoadData() {
+ // should merge continuous binary data into one big lump or several big lumps if duty cycled.
+ OfflineDataMap dataMap = findDataMap();
+ if (dataMap == null) {
+ return;
+ }
+ ArrayList allPoints = new ArrayList<>();
+ Iterator it = dataMap.getListIterator();
+ DataMapEffortThing currentThing = null;
+ while (it.hasNext()) {
+ OfflineDataMapPoint pt = it.next();
+ if (currentThing == null || pt.getStartTime() - currentThing.getEffortEnd() > maxGap) {
+ currentThing = new DataMapEffortThing(this, getParentDataBlock(), pt.getStartTime(), pt.getEndTime());
+ allPoints.add(currentThing);
+ }
+ else {
+ currentThing.setEffortEnd(pt.getEndTime());
+ }
+ }
+
+ allEfforts = allPoints;
+
+ }
+
+}
diff --git a/src/effort/binary/DataMapEffortThing.java b/src/effort/binary/DataMapEffortThing.java
new file mode 100644
index 00000000..8c270bf1
--- /dev/null
+++ b/src/effort/binary/DataMapEffortThing.java
@@ -0,0 +1,22 @@
+package effort.binary;
+
+import PamguardMVC.PamDataBlock;
+import effort.EffortDataUnit;
+import effort.EffortProvider;
+
+public class DataMapEffortThing extends EffortDataUnit {
+
+
+ private PamDataBlock parentDatablock;
+
+ public DataMapEffortThing(EffortProvider effortProvider, PamDataBlock parentDatablock, long effortStart, long effortEnd) {
+ super(effortProvider, null, effortStart, effortEnd);
+ this.parentDatablock = parentDatablock;
+ }
+
+ @Override
+ public String getEffortDescription() {
+ String str = String.format("%s", parentDatablock.getDataName());
+ return str;
+ }
+}
diff --git a/src/effort/binary/DataMapSymbolManager.java b/src/effort/binary/DataMapSymbolManager.java
new file mode 100644
index 00000000..4243d0dc
--- /dev/null
+++ b/src/effort/binary/DataMapSymbolManager.java
@@ -0,0 +1,18 @@
+package effort.binary;
+
+import PamView.symbol.PamSymbolChooser;
+import PamView.symbol.StandardSymbolManager;
+import PamView.symbol.SymbolData;
+import PamView.symbol.SymbolOnlyManager;
+import PamguardMVC.PamDataBlock;
+
+public class DataMapSymbolManager extends SymbolOnlyManager {
+
+ public static SymbolData defaultSymbol = new SymbolData();
+
+ public DataMapSymbolManager(PamDataBlock pamDataBlock) {
+ super(pamDataBlock, defaultSymbol);
+ }
+
+
+}
diff --git a/src/effort/swing/EffortSourcePanel.java b/src/effort/swing/EffortSourcePanel.java
new file mode 100644
index 00000000..b47e7c3c
--- /dev/null
+++ b/src/effort/swing/EffortSourcePanel.java
@@ -0,0 +1,28 @@
+package effort.swing;
+
+import java.awt.Window;
+import java.util.ArrayList;
+
+import PamView.dialog.SourcePanel;
+import PamguardMVC.PamDataBlock;
+import effort.EffortManager;
+
+public class EffortSourcePanel extends SourcePanel {
+
+ public EffortSourcePanel(Window ownerWindow) {
+ super(ownerWindow, PamDataBlock.class, false, false);
+ }
+
+ public EffortSourcePanel(Window ownerWindow, String borderTitle) {
+ super(ownerWindow, borderTitle, PamDataBlock.class, false, false);
+ }
+
+ @Override
+ public ArrayList getCompatibleDataBlocks() {
+ return EffortManager.getEffortManager().getEffortDataBlocks();
+ }
+
+
+
+
+}
diff --git a/src/effortmonitor/EffortControl.java b/src/effortmonitor/EffortControl.java
index a15b1cf2..b8e9e760 100644
--- a/src/effortmonitor/EffortControl.java
+++ b/src/effortmonitor/EffortControl.java
@@ -33,6 +33,11 @@ import pamScrollSystem.PamScroller;
import pamScrollSystem.PamScrollerData;
import userDisplay.UserDisplayControl;
+/**
+ * Record scroll effort.
+ * @author dg50
+ *
+ */
public class EffortControl extends PamControlledUnit implements PamSettings{
public static String unitType = "Scroll Effort";
diff --git a/src/generalDatabase/DBMapMakingDialog.java b/src/generalDatabase/DBMapMakingDialog.java
index 52c44092..7cc791fb 100644
--- a/src/generalDatabase/DBMapMakingDialog.java
+++ b/src/generalDatabase/DBMapMakingDialog.java
@@ -32,8 +32,8 @@ public class DBMapMakingDialog extends PamDialog {
JPanel p = new JPanel();
p.setBorder(new TitledBorder("Creating data map"));
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
- p.add(databaseName = new JLabel(""));
- p.add(streamName = new JLabel(""));
+ p.add(databaseName = new JLabel(" "));
+ p.add(streamName = new JLabel(" "));
p.add(streamProgress = new JProgressBar());
// p.setPreferredSize(new Dimension(400, 200));
streamName.setPreferredSize(new Dimension(250, 5));
diff --git a/src/generalDatabase/lookupTables/LookUpTables.java b/src/generalDatabase/lookupTables/LookUpTables.java
index abea6653..75ba15af 100644
--- a/src/generalDatabase/lookupTables/LookUpTables.java
+++ b/src/generalDatabase/lookupTables/LookUpTables.java
@@ -144,11 +144,14 @@ public class LookUpTables {
String topic1 = list.get(i).getTopic().trim();
for (int j = i+1; j < n; j++) {
String code2 = list.get(j).getCode().trim();
- String topic2 = list.get(j).getTopic().trim();
+ String topic2 = list.get(j).getTopic();
+ if (topic2 != null) {
+ topic2 = topic2.trim();
if (code.equals(code2) && topic1.equals(topic2)) {
isRepeat[j] = true;
nRepeat++;
}
+ }
}
}
if (nRepeat == 0) {
@@ -183,7 +186,7 @@ public class LookUpTables {
return null;
}
ArrayList topics = new ArrayList<>();
- String qStr = "SELECT DISTINCT Topic FROM " + lutTableDef.getTableName();
+ String qStr = "SELECT DISTINCT Topic FROM " + lutTableDef.getTableName() + " WHERE TOPIC IS NOT NULL";
try {
Statement stmt = con.getConnection().createStatement();
boolean ok = stmt.execute(qStr);
diff --git a/src/group3dlocaliser/Group3DParams.java b/src/group3dlocaliser/Group3DParams.java
index 6467a9ad..b455494a 100644
--- a/src/group3dlocaliser/Group3DParams.java
+++ b/src/group3dlocaliser/Group3DParams.java
@@ -17,8 +17,8 @@ public class Group3DParams implements Serializable, Cloneable, ManagedParameters
public static final long serialVersionUID = 1L;
- @Deprecated
- private GroupedSourceParameters groupedSourceParams;
+// @Deprecated
+// private GroupedSourceParameters groupedSourceParams;
private String sourceName;
@@ -146,9 +146,9 @@ public class Group3DParams implements Serializable, Cloneable, ManagedParameters
* @return the sourceName
*/
public String getSourceName() {
- if (sourceName == null && groupedSourceParams != null) {
- sourceName = groupedSourceParams.getDataSource();
- }
+// if (sourceName == null && groupedSourceParams != null) {
+// sourceName = groupedSourceParams.getDataSource();
+// }
return sourceName;
}
diff --git a/src/loggerForms/FormDescription.java b/src/loggerForms/FormDescription.java
index a212b94d..b6d862e7 100644
--- a/src/loggerForms/FormDescription.java
+++ b/src/loggerForms/FormDescription.java
@@ -56,7 +56,6 @@ import pamScrollSystem.AbstractPamScrollerAWT;
import pamScrollSystem.ScrollPaneAddon;
import PamView.PamTabPanel;
import PamView.panel.PamPanel;
-import PamView.symbol.StandardSymbolManager;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import PamController.PamControlledUnitSettings;
@@ -67,7 +66,6 @@ import PamUtils.PamCalendar;
import PamUtils.XMLUtils;
import loggerForms.controlDescriptions.ControlTypes;
import loggerForms.controlDescriptions.InputControlDescription;
-import loggerForms.PropertyTypes;
import loggerForms.controlDescriptions.ControlDescription;
import loggerForms.formdesign.FormEditDialog;
import loggerForms.formdesign.FormEditor;
@@ -75,6 +73,7 @@ import loggerForms.formdesign.FormList;
import loggerForms.propertyInfos.BEARINGinfo;
import loggerForms.propertyInfos.HEADINGinfo;
import loggerForms.propertyInfos.RANGEinfo;
+import loggerForms.symbol.LoggerSymbolManager;
/**
*
* @author Graham Weatherup - SMRU
@@ -242,7 +241,7 @@ public class FormDescription implements Cloneable, Comparable {
formsDataBlock = new FormsDataBlock(this, getFormName(), formsControl.getFormsProcess(), 0);
formsDataBlock.SetLogging(new FormsLogging(this,formsDataBlock));
formsDataBlock.setOverlayDraw(new LoggerFormGraphics(formsControl, this));
- formsDataBlock.setPamSymbolManager(new StandardSymbolManager(formsDataBlock, LoggerFormGraphics.defaultSymbol, false));
+ formsDataBlock.setPamSymbolManager(new LoggerSymbolManager(formsDataBlock));
setTimeOfNextSave();
@@ -1068,7 +1067,7 @@ public class FormDescription implements Cloneable, Comparable {
normalForm = createForm();
formComponent = normalForm.getComponent();
}
- formsDataDisplayTable = new FormsDataDisplayTable(this);
+ formsDataDisplayTable = new FormsDataDisplayTable(formsControl, this);
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, formComponent, formsDataDisplayTable.getMainPanel());
if (formSettingsControl.getFormSettings().splitPanelPosition != null) {
@@ -1122,7 +1121,8 @@ public class FormDescription implements Cloneable, Comparable {
}
public LoggerForm createForm() {
- return new LoggerForm(this,LoggerForm.NewDataForm);
+ boolean viewer = PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW;
+ return new LoggerForm(this, viewer ? LoggerForm.NewDataForm : LoggerForm.NewDataForm);
}
@@ -1230,6 +1230,22 @@ public class FormDescription implements Cloneable, Comparable {
removeForm(parentFrame);
}
}
+
+ /**
+ * Delete a data unit from memory and from database.
+ * @param dataUnit
+ * @return
+ */
+ public boolean deleteDataUnit(FormsDataUnit dataUnit) {
+ if (dataUnit == null) {
+ return false;
+ }
+ boolean ans = getFormsDataBlock().remove(dataUnit, true);
+ if (formsDataDisplayTable != null) {
+ formsDataDisplayTable.dataChanged();
+ }
+ return ans;
+ }
/**
* Create a new subtab form on the appropriate sub tab panel.
*/
@@ -1646,6 +1662,15 @@ public class FormDescription implements Cloneable, Comparable {
normalForm.restoreData(formsDataUnit);
}
}
+
+ public void optionsChange() {
+ if (normalForm != null) {
+ normalForm.optionsChange();
+ }
+ if (formsDataDisplayTable != null) {
+ formsDataDisplayTable.optionsChange();
+ }
+ }
/**
* Get a count of open sub tab forms.
diff --git a/src/loggerForms/FormsControl.java b/src/loggerForms/FormsControl.java
index 94cf9112..ba34a520 100644
--- a/src/loggerForms/FormsControl.java
+++ b/src/loggerForms/FormsControl.java
@@ -16,6 +16,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.LogManager;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
@@ -34,6 +35,7 @@ import loggerForms.FormDescription.FormPlotOptionsStore;
import loggerForms.monitor.FormsMonitorMaster;
import PamController.PamControlledUnit;
import PamController.PamControlledUnitSettings;
+import PamController.PamController;
import PamController.PamControllerInterface;
import PamController.PamSettingManager;
import PamController.PamSettings;
@@ -48,16 +50,14 @@ import PamView.PamTabPanel;
import PamView.PamView;
import PamguardMVC.PamDataBlock;
-
/**
*
- * @author Graham Weatherup
- * controls the logger forms module
+ * @author Graham Weatherup controls the logger forms module
*/
-public class FormsControl extends PamControlledUnit {
+public class FormsControl extends PamControlledUnit implements PamSettings {
public static ArrayList restrictedTitles = new ArrayList();
-
+
private ArrayList formDescriptions = new ArrayList();
private ArrayList UDFErrors = new ArrayList();
@@ -66,11 +66,13 @@ public class FormsControl extends PamControlledUnit {
private FormsAlertSidePanel formsAlertSidePanel;
private FormsProcess formsProcess;
-
+
public static final String unitType = "Logger Forms";
-
+
private FormsMonitorMaster formsMonitor;
-
+
+ private FormsParameters formsParameters = new FormsParameters();
+
// /** A set of dummy parameters, used solely to pull together different settings for XML export */
// private FormsTempParams dummyParams;
@@ -83,8 +85,7 @@ public class FormsControl extends PamControlledUnit {
formsTabPanel = new FormsTabPanel(this);
formsAlertSidePanel = new FormsAlertSidePanel(this);
formsMonitor = new FormsMonitorMaster(this, formsProcess);
-// dummyParams = new FormsTempParams();
-// PamSettingManager.getInstance().registerSettings(this);
+ PamSettingManager.getInstance().registerSettings(this);
}
@@ -100,7 +101,7 @@ public class FormsControl extends PamControlledUnit {
*
*/
private boolean buildRestrictedTitles() {
-
+
DBControlUnit dbControl = DBControlUnit.findDatabaseControl();
if (dbControl == null) {
return false;
@@ -108,30 +109,29 @@ public class FormsControl extends PamControlledUnit {
String keywordString = null;
try {
keywordString = DBControlUnit.findDatabaseControl().getDatabaseSystem().getKeywords();
- }
- catch (NullPointerException e) {
+ } catch (NullPointerException e) {
return false;
}
-
+
String[] keywords;
if (keywordString != null) {
keywords = keywordString.split(",");
- for (String k:keywords){
+ for (String k : keywords) {
restrictedTitles.add(k);
}
}
-
+
try {
PamConnection con = DBControlUnit.findConnection();
if (con == null) {
return false;
}
keywordString = con.getConnection().getMetaData().getSQLKeywords();
-
+
keywords = keywordString.split(",");
-
- for (String k:keywords){
+
+ for (String k : keywords) {
restrictedTitles.add(k);
}
// System.out.println(keywordString);
@@ -141,20 +141,21 @@ public class FormsControl extends PamControlledUnit {
} catch (SQLException e) {
e.printStackTrace();
return false;
- }
- catch (Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
return false;
}
-
+
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see PamController.PamControlledUnit#notifyModelChanged(int)
*/
@Override
public void notifyModelChanged(int changeType) {
- switch(changeType) {
+ switch (changeType) {
case PamControllerInterface.INITIALIZATION_COMPLETE:
generateForms();
break;
@@ -173,29 +174,32 @@ public class FormsControl extends PamControlledUnit {
/**
* Get the form description for a specific index.
+ *
* @param iForm form index
* @return for description
*/
public FormDescription getFormDescription(int iForm) {
return formDescriptions.get(iForm);
}
-
+
/**
* Get a form index from a form description
+ *
* @param formDescription Form Descriptions
* @return form index or -1 if not found
*/
public int getFormIndex(FormDescription formDescription) {
return formDescriptions.indexOf(formDescription);
}
-
+
/**
- * Find a form which has a particular order value.
+ * Find a form which has a particular order value.
+ *
* @param order order (starts from 1 generally)
- * @return a form, or null if none have that order.
+ * @return a form, or null if none have that order.
*/
public FormDescription findFormByOrder(int order) {
- for (FormDescription aForm:formDescriptions) {
+ for (FormDescription aForm : formDescriptions) {
PropertyDescription formProperty = aForm.findProperty(PropertyTypes.ORDER);
if (formProperty == null) {
continue;
@@ -210,6 +214,7 @@ public class FormsControl extends PamControlledUnit {
/**
* Find a form description with a given name.
+ *
* @param formName
* @return form description or null.
*/
@@ -217,7 +222,7 @@ public class FormsControl extends PamControlledUnit {
if (formName == null) {
return null;
}
- for (FormDescription ad:formDescriptions) {
+ for (FormDescription ad : formDescriptions) {
if (ad.getFormName().equals(formName)) {
return ad;
}
@@ -227,41 +232,40 @@ public class FormsControl extends PamControlledUnit {
}
return null;
}
-
- public Character getOutputTableNameCounterSuffix(FormDescription thisFormDescription){
-
+
+ public Character getOutputTableNameCounterSuffix(FormDescription thisFormDescription) {
+
String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String thisTableName = thisFormDescription.getDBTABLENAME();
- int count=0;
+ int count = 0;
int position = 0;
-
- for (FormDescription formDescription : formDescriptions){
- if ((formDescription.getDBTABLENAME()==thisFormDescription.getDBTABLENAME())){
- position=count;
+
+ for (FormDescription formDescription : formDescriptions) {
+ if ((formDescription.getDBTABLENAME() == thisFormDescription.getDBTABLENAME())) {
+ position = count;
break;
}
-
+
count++;
-
+
}
- // if (count==0){
- // return "";
- // }else{
- // return Character.;
- // Integer.toString(arg0, arg1)
- // System.out.println("*********");
- // System.out.println(position);
-
- // }
- // System.out.println(letters.charAt(position));
- // System.out.println("*********");
+ // if (count==0){
+ // return "";
+ // }else{
+ // return Character.;
+ // Integer.toString(arg0, arg1)
+ // System.out.println("*********");
+ // System.out.println(position);
+
+ // }
+ // System.out.println(letters.charAt(position));
+ // System.out.println("*********");
return letters.charAt(position);
}
-
/**
- * Generates a list of tables beginning with UDF_ and reads
- * their contents into a FormDescription
+ * Generates a list of tables beginning with UDF_ and reads their contents into
+ * a FormDescription
*/
public void readUDFTables() {
/*
@@ -281,7 +285,7 @@ public class FormsControl extends PamControlledUnit {
ArrayList udfTableNameList = new ArrayList();
PamConnection dbCon = dbControl.getConnection();
-
+
if (dbCon == null) {
System.out.println("Database not opened: Logger forms cannot be read");
return;
@@ -289,42 +293,38 @@ public class FormsControl extends PamControlledUnit {
try {
DatabaseMetaData dbmd = dbCon.getConnection().getMetaData();
- String[] types = {"TABLE"};
- ResultSet resultSet = dbmd.getTables(null, null, "%", types);//not getting all tables from db in ODB
+ String[] types = { "TABLE" };
+ ResultSet resultSet = dbmd.getTables(null, null, "%", types);// not getting all tables from db in ODB
-
-
- //Loop through database tables
- while (resultSet.next()){
+ // Loop through database tables
+ while (resultSet.next()) {
String tableName = resultSet.getString(3);
// System.out.println("LogFor: "+tableName);
- //If starts with 'UDF_' create form description from it.
- if( tableName.toUpperCase().startsWith("UDF_")){
+ // If starts with 'UDF_' create form description from it.
+ if (tableName.toUpperCase().startsWith("UDF_")) {
udfTableNameList.add(tableName);
}
}
-
} catch (SQLException e) {
e.printStackTrace();
}
-
- if (UDFErrors.size()>0){
+ if (UDFErrors.size() > 0) {
}
- for (String tableName:udfTableNameList){
+ for (String tableName : udfTableNameList) {
FormDescription formDescription = new FormDescription(this, tableName);
formDescriptions.add(formDescription);
}
-
- // at this point, before datablocks are created, sort the forms into order.
+
+ // at this point, before datablocks are created, sort the forms into order.
Collections.sort(formDescriptions);
// hotKeyControl.removeAllListeners();
- // finally create the datablocks.
- // at the same time, can reset the order properties to a simple sequence.
+ // finally create the datablocks.
+ // at the same time, can reset the order properties to a simple sequence.
int iForm = 0;
- for (FormDescription aFD:formDescriptions) {
+ for (FormDescription aFD : formDescriptions) {
formsProcess.addOutputDataBlock(aFD.getFormsDataBlock());
aFD.setFormOrderProperty(++iForm);
/*
@@ -338,21 +338,24 @@ public class FormsControl extends PamControlledUnit {
}
}
-
- public void addFormDescription(String newFormName){
+
+ public void addFormDescription(String newFormName) {
FormDescription formDescription = new FormDescription(this, newFormName);
formsProcess.addOutputDataBlock(formDescription.getFormsDataBlock());
}
/**
- * Get the correct type of reference to the forms tab panel.
- * @return reference to the forms tab panel.
+ * Get the correct type of reference to the forms tab panel.
+ *
+ * @return reference to the forms tab panel.
*/
public FormsTabPanel getFormsTabPanel() {
return formsTabPanel;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see PamController.PamControlledUnit#getTabPanel()
*/
@Override
@@ -372,8 +375,6 @@ public class FormsControl extends PamControlledUnit {
}
-
-
/**
* @return the formsProcess
*/
@@ -381,7 +382,9 @@ public class FormsControl extends PamControlledUnit {
return formsProcess;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see PamController.PamControlledUnit#createDetectionMenu(java.awt.Frame)
*/
@Override
@@ -391,27 +394,38 @@ public class FormsControl extends PamControlledUnit {
detMenu.add(menuItem);
menuItem.addActionListener(new NewLoggerForm(parentFrame));
// if (SMRUEnable.isEnable()) {
- JMenu editMenu = new JMenu("Edit form");
- for (int i = 0; i < getNumFormDescriptions(); i++) {
- FormDescription fd = getFormDescription(i);
- JMenuItem fm = new JMenuItem(fd.getFormName() + "...");
- fm.addActionListener(new EditForm(parentFrame, fd));
- editMenu.add(fm);
- }
- detMenu.add(editMenu);
+ JMenu editMenu = new JMenu("Edit form");
+ for (int i = 0; i < getNumFormDescriptions(); i++) {
+ FormDescription fd = getFormDescription(i);
+ JMenuItem fm = new JMenuItem(fd.getFormName() + "...");
+ fm.addActionListener(new EditForm(parentFrame, fd));
+ editMenu.add(fm);
+ }
+ detMenu.add(editMenu);
// }
detMenu.add(menuItem = new JMenuItem("Regenerate all forms"));
menuItem.addActionListener(new ReGenerateForms(parentFrame));
-
-
-
+ if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
+ JCheckBoxMenuItem changebox = new JCheckBoxMenuItem("Allow Viewer changes");
+ changebox.setToolTipText("Allow the editing, adding, and deleting of data in Viewer mode");
+ changebox.setSelected(formsParameters.allowViewerChanges);
+ changebox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ formsParameters.allowViewerChanges = changebox.isSelected();
+ notifyOptionsChange();
+ }
+ });
+ detMenu.add(changebox);
+ }
+
return detMenu;
}
class NewLoggerForm implements ActionListener {
-
+
private Frame parentFrame;
-
+
public NewLoggerForm(Frame parentFrame) {
this.parentFrame = parentFrame;
}
@@ -419,15 +433,22 @@ public class FormsControl extends PamControlledUnit {
@Override
public void actionPerformed(ActionEvent arg0) {
newLoggerform(parentFrame);
-
}
-
+ }
+
+ private void notifyOptionsChange() {
+ if (formDescriptions == null) {
+ return;
+ }
+ for (FormDescription formDesc: formDescriptions) {
+ formDesc.optionsChange();
+ }
}
class ReGenerateForms implements ActionListener {
-
+
private Frame parentFrame;
-
+
public ReGenerateForms(Frame parentFrame) {
this.parentFrame = parentFrame;
}
@@ -435,37 +456,41 @@ public class FormsControl extends PamControlledUnit {
@Override
public void actionPerformed(ActionEvent arg0) {
regenerateForms(parentFrame);
-
+
}
-
+
}
-
+
class EditForm implements ActionListener {
private FormDescription formDescription;
private Frame parentFrame;
+
public EditForm(Frame parentFrame, FormDescription formDescription) {
super();
this.parentFrame = parentFrame;
this.formDescription = formDescription;
}
+
@Override
public void actionPerformed(ActionEvent arg0) {
this.formDescription.editForm(parentFrame);
}
}
-
+
/**
* Create a new logger form
+ *
* @param parentFrame parent frame
- * @return selected name for new form, or null if nothing created.
+ * @return selected name for new form, or null if nothing created.
*/
public String newLoggerform(Frame parentFrame) {
- String newName = JOptionPane.showInputDialog(parentFrame, "Enter the name for the new user form", "New Logger Form", JOptionPane.OK_CANCEL_OPTION);
+ String newName = JOptionPane.showInputDialog(parentFrame, "Enter the name for the new user form",
+ "New Logger Form", JOptionPane.OK_CANCEL_OPTION);
if (newName == null) {
return null;
}
// will make a form table definition with a standard structure and name UDF_ ...
- // check the current name starts with UDF and add if necessary.
+ // check the current name starts with UDF and add if necessary.
if (newName.toUpperCase().startsWith("UDF_") == false) {
newName = "UDF_" + newName;
}
@@ -473,11 +498,11 @@ public class FormsControl extends PamControlledUnit {
message += "\nNote that youwill have to exit PAMGUARD and enter form control data by hand into this table.";
message += "\nFuture releases will (hopefully) contain a more friendly programmable interface";
int ans = JOptionPane.showConfirmDialog(parentFrame, message, "Create Form", JOptionPane.OK_CANCEL_OPTION);
- if(ans == JOptionPane.CANCEL_OPTION) {
+ if (ans == JOptionPane.CANCEL_OPTION) {
return null;
}
UDFTableDefinition tableDef = new UDFTableDefinition(newName);
- message = String.format("The table %s could not be created in the databse %s", newName,
+ message = String.format("The table %s could not be created in the databse %s", newName,
DBControlUnit.findDatabaseControl().getDatabaseName());
if (DBControlUnit.findDatabaseControl().getDbProcess().checkTable(tableDef) == false) {
JOptionPane.showMessageDialog(parentFrame, "Error Creating form", message, JOptionPane.ERROR_MESSAGE);
@@ -485,33 +510,32 @@ public class FormsControl extends PamControlledUnit {
return newName;
}
-
/**
* Generate all forms and associated processes, notifying databases, maps, etc
- * so that any required actions can be taken.
+ * so that any required actions can be taken.
*/
private void generateForms() {
buildRestrictedTitles();
-
+
readUDFTables();
createProcesses();
-
+
formsTabPanel.createForms();
- // initialise
+ // initialise
DBControlUnit dbControl = DBControlUnit.findDatabaseControl();
if (dbControl == null) {
return;
}
-
+
DBControlUnit.findDatabaseControl().getDbProcess().updateProcessList();
if (isViewer) {
updateFormDataMaps();
}
-
- formsAlertSidePanel.getFormsAlertPanel().updateFormsShowing();
+
+ formsAlertSidePanel.getFormsAlertPanel().updateFormsShowing();
// will also at this point need to tell the main gui frame to update
// it's menu since it needs to incorporate a list of forms for editing
PamView pamView = getPamView();
@@ -522,22 +546,23 @@ public class FormsControl extends PamControlledUnit {
formsMonitor.rebuiltForms();
}
-
+
/**
- * Delete and recreate all forms / form data, etc.
+ * Delete and recreate all forms / form data, etc.
+ *
* @param parentFrame
*/
public void regenerateForms(Window parentFrame) {
formsTabPanel.removeAllForms();
-
- for (FormDescription formDescription:formDescriptions) {
+
+ for (FormDescription formDescription : formDescriptions) {
formDescription.destroyForms();
}
formDescriptions.clear();
formsProcess.removeAllDataBlocks();
generateForms();
FormsPlotOptionsDialog.deleteDialog();
-
+
}
@Override
@@ -565,14 +590,16 @@ public class FormsControl extends PamControlledUnit {
boolean ans = FormsPlotOptionsDialog.showDialog(parentFrame, this);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see PamController.PamControlledUnit#canClose()
*/
@Override
public boolean canClose() {
// return false if any forms have open sub forms.
int subFormCount = 0;
- for (FormDescription fd:formDescriptions) {
+ for (FormDescription fd : formDescriptions) {
subFormCount += fd.getSubformCount();
}
if (subFormCount == 0) {
@@ -584,10 +611,10 @@ public class FormsControl extends PamControlledUnit {
}
/**
- * Rewrite all UDF tables in forms which have been altered.
+ * Rewrite all UDF tables in forms which have been altered.
*/
public void rewriteChangedUDFTables() {
- for (FormDescription aForm:formDescriptions) {
+ for (FormDescription aForm : formDescriptions) {
if (aForm.isNeedsUDFSave()) {
aForm.writeUDFTable(null);
aForm.setNeedsUDFSave(false);
@@ -614,10 +641,10 @@ public class FormsControl extends PamControlledUnit {
return new ModuleStatus(ModuleStatus.STATUS_OK);
}
-
/**
- * Some things that are meant to be boolean are coming out as int or string so
- * need to do some type checking.
+ * Some things that are meant to be boolean are coming out as int or string so
+ * need to do some type checking.
+ *
* @param value
* @return
*/
@@ -637,48 +664,31 @@ public class FormsControl extends PamControlledUnit {
int val = (Integer) value;
return val != 0;
}
-
+
return null;
}
-// @Override
-// public Serializable getSettingsReference() {
-// return (Serializable) dummyParams;
-// }
-//
-// @Override
-// public long getSettingsVersion() {
-// return 0;
-// }
-//
-// @Override
-// public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
-// return false;
-// }
-//
-// /**
-// * Private class to pass along various parameter classes that Logger forms use
-// *
-// * @author mo55
-// *
-// */
-// private class FormsTempParams implements ManagedParameters {
-//
-// @Override
-// public PamParameterSet getParameterSet() {
-// PamParameterSet ps = new PamParameterSet(this);
-// try {
-// Field field = FormsControl.this.getClass().getDeclaredField("formDescriptions");
-// ps.put(new PrivatePamParameterData(this, field) {
-// @Override
-// public Object getData() throws IllegalArgumentException, IllegalAccessException {
-// return formDescriptions;
-// }
-// });
-// } catch (NoSuchFieldException | SecurityException e) {
-// e.printStackTrace();
-// }
-// return ps;
-// }
-// }
+
+ @Override
+ public Serializable getSettingsReference() {
+ return formsParameters;
+ }
+
+ @Override
+ public long getSettingsVersion() {
+ return FormsParameters.serialVersionUID;
+ }
+
+ @Override
+ public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
+ this.formsParameters = (FormsParameters) pamControlledUnitSettings.getSettings();
+ return true;
+ }
+
+ /**
+ * @return the formsParameters
+ */
+ public FormsParameters getFormsParameters() {
+ return formsParameters;
+ }
}
diff --git a/src/loggerForms/FormsDataBlock.java b/src/loggerForms/FormsDataBlock.java
index ff6aa1a1..220ae3ba 100644
--- a/src/loggerForms/FormsDataBlock.java
+++ b/src/loggerForms/FormsDataBlock.java
@@ -7,6 +7,8 @@ import PamguardMVC.PamProcess;
import PamguardMVC.dataSelector.DataSelector;
import PamguardMVC.dataSelector.DataSelectorCreator;
import loggerForms.dataselect.FormDataSelCreator;
+import loggerForms.effort.FormsEffortUnit;
+import loggerForms.effort.LoggerEffortProvider;
import loggerForms.monitor.FormsDataSelectorCreator;
/**
*
@@ -16,6 +18,8 @@ import loggerForms.monitor.FormsDataSelectorCreator;
public class FormsDataBlock extends PamDataBlock {
private FormDescription formDescription;
+
+ private LoggerEffortProvider loggerEffortProvider;
public FormsDataBlock(FormDescription formDescription, String dataName,
PamProcess parentProcess, int channelMap) {
@@ -25,6 +29,7 @@ public class FormsDataBlock extends PamDataBlock {
setDataSelectCreator(new FormDataSelCreator(this, formDescription));
// setBinaryDataSource(new FormsBinaryIO(formDescription.getFormsControl(), this));
// setNaturalLifetimeMillis(60000);
+ setEffortProvider(loggerEffortProvider = new LoggerEffortProvider(this));
}
public FormDescription getFormDescription() {
diff --git a/src/loggerForms/FormsDataDisplayTable.java b/src/loggerForms/FormsDataDisplayTable.java
index 1300fc79..011739f2 100644
--- a/src/loggerForms/FormsDataDisplayTable.java
+++ b/src/loggerForms/FormsDataDisplayTable.java
@@ -4,10 +4,15 @@
package loggerForms;
import java.awt.GridLayout;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import javax.swing.JMenuItem;
import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
@@ -20,6 +25,7 @@ import PamController.PamController;
import PamUtils.PamCalendar;
import PamView.PamTable;
import PamView.dialog.PamDialog;
+import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
/**
@@ -37,11 +43,13 @@ public class FormsDataDisplayTable {
private JScrollPane scrollPane;
+ private FormsControl formsControl;
+
/**
* @param formDescription
*/
- public FormsDataDisplayTable(FormDescription formDescription) {
- // TODO Auto-generated constructor stub
+ public FormsDataDisplayTable(FormsControl formsControl, FormDescription formDescription) {
+ this.formsControl = formsControl;
this.formDescription=formDescription;
// GridLayout(rows,columns)
@@ -63,36 +71,16 @@ public class FormsDataDisplayTable {
formsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
// for now, don't allow edits in viewer mode.
- if (PamController.getInstance().getRunMode() != PamController.RUN_PAMVIEW) {
+// if (PamController.getInstance().getRunMode() != PamController.RUN_PAMVIEW) {
formsTable.addMouseListener(new EditDataListener());
- }
+// }
scrollPane = new JScrollPane(formsTable);
mainPanel.add(scrollPane);
-
-// mainPanel.setPreferredSize(new Dimension(800, 200));
-
-
-
}
-// class TimerListener implements ActionListener {
-// boolean doneLayout;
-// public void actionPerformed(ActionEvent ev) {
-// // table.
-//// nmeaTableData.fireTableRowsUpdated(0, 10);
-// formsTableDataModel.fireTableDataChanged();
-//
-// if (doneLayout == false && formsTableDataModel.getRowCount() > 0) {
-// doneLayout = true;
-// }
-// }
-// }
-
-
-
class TableListListener implements ListSelectionListener {
@Override
@@ -108,9 +96,15 @@ public class FormsDataDisplayTable {
formDescription.viewDataUnit(formsDataUnit);
}
}
-
}
+ private boolean canEdit() {
+ if (PamController.getInstance().getRunMode() != PamController.RUN_PAMVIEW) {
+ return true;
+ }
+ if (formsControl == null) return false;
+ return formsControl.getFormsParameters().allowViewerChanges;
+ }
/**
* Find the data unit for a particular row in the table.
* @param iRow
@@ -125,9 +119,11 @@ public class FormsDataDisplayTable {
class EditDataListener extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e) {
+ if (canEdit() == false) {
+ return;
+ }
if (e.getClickCount() == 2) {
-// FormsDataBlock formsDataBlock = formDescription.getFormsDataBlock();
int row = formsTable.getSelectedRow();
FormsDataUnit formsDataUnit = findDataUnitForRow(row);
@@ -135,14 +131,32 @@ public class FormsDataDisplayTable {
PamDialog.showWarning(null, "WARNING", "could not find formsDataUnit");
return;
}
-
-
-
- FormsDataUnitEditor due = new FormsDataUnitEditor(formDescription,formsDataUnit);
-
+ editDataUnit(formsDataUnit);
}
}
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ maybePopup(e);
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ maybePopup(e);
+ }
+
+ private void maybePopup(MouseEvent e) {
+ if (e.isPopupTrigger() == false) {
+ return;
+ }
+ if (canEdit() == false) {
+ return;
+ }
+ int row = formsTable.getSelectedRow();
+
+ showPopupMenu(e.getPoint());
+ }
}
@@ -259,9 +273,69 @@ public class FormsDataDisplayTable {
return mainPanel;
}
+ public void showPopupMenu(Point pt) {
+
+ FormsDataUnit dataUnit = findDataUnitForRow(formsTable.getSelectedRow());
+ JPopupMenu menu = new JPopupMenu();
+ JMenuItem menuItem;
+ if (dataUnit != null) {
+ menuItem = new JMenuItem("Edit row ...");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ editDataUnit(dataUnit);
+ }
+ });
+ menu.add(menuItem);
+ }
+ menuItem = new JMenuItem("Create row ...");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ addDataUnit();
+ }
+ });
+ menu.add(menuItem);
+
+ if (dataUnit != null) {
+ menu.addSeparator();
+ menuItem = new JMenuItem("Delete row ...");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ deleteDataUnit(dataUnit);
+ }
+ });
+ menu.add(menuItem);
+ }
+ menu.show(formsTable, pt.x, pt.y);
+ }
+
+ private boolean editDataUnit(FormsDataUnit dataUnit) {
+ FormsDataUnitEditor due = new FormsDataUnitEditor(formDescription, dataUnit);
+ return true;
+ }
+
+ private boolean deleteDataUnit(FormsDataUnit dataUnit) {
+ if (dataUnit == null) {
+ return false;
+ }
+ int ans = WarnOnce.showWarning("Delete logger form data", "Are you sure you want to delete data Id " + dataUnit.getDatabaseIndex(), WarnOnce.OK_CANCEL_OPTION);
+ if (ans != WarnOnce.OK_OPTION) {
+ return false;
+ }
+ formDescription.deleteDataUnit(dataUnit);
+ return true;
+ }
+
+ private boolean addDataUnit() {
+ formDescription.viewDataUnit(null);
+ return false;
+ }
+
/**
* Called when data have changed in the datablock.
*/
@@ -276,4 +350,12 @@ public class FormsDataDisplayTable {
public JScrollPane getScrollPane() {
return scrollPane;
}
+
+ /**
+ * Some optins have changed.
+ */
+ public void optionsChange() {
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/src/loggerForms/FormsDataUnit.java b/src/loggerForms/FormsDataUnit.java
index 32ab905d..30cb4f0a 100644
--- a/src/loggerForms/FormsDataUnit.java
+++ b/src/loggerForms/FormsDataUnit.java
@@ -2,7 +2,10 @@ package loggerForms;
import GPS.GpsData;
import PamUtils.PamCalendar;
+import PamView.GeneralProjector;
import PamguardMVC.PamDataUnit;
+import generalDatabase.SQLTypes;
+import loggerForms.controlDescriptions.ControlDescription;
/**
*
* @author Graham Weatherup
@@ -12,9 +15,6 @@ import PamguardMVC.PamDataUnit;
* UTCmillisecond
* PCLocalTime
*
- *
- *
- *
*/
public class FormsDataUnit extends PamDataUnit {
@@ -94,6 +94,82 @@ public class FormsDataUnit extends PamDataUnit {
return formOriginLatLong;
}
+ @Override
+ public long getTimeMilliseconds() {
+ Long time = findTimeValue(PropertyTypes.STARTTIME);
+ if (time != null) {
+ return time;
+ }
+ return super.getTimeMilliseconds();
+ }
+
+ /**
+ * Find one of the time property controls and get its value.
+ * @param timeProperty
+ * @return
+ */
+ public Long findTimeValue(PropertyTypes timeProperty) {
+ if (formData == null) {
+ return null;
+ }
+ PropertyDescription prop = formDescription.findProperty(timeProperty);
+ if (prop == null) {
+ return null;
+ }
+ String ctrlTitle = prop.getItemInformation().getStringProperty("Title");
+ if (ctrlTitle == null) {
+ return null;
+ }
+ int timeControlIndex = formDescription.findInputControlByName(ctrlTitle);
+ if (timeControlIndex < 0 || timeControlIndex >= formData.length) {
+ return null;
+ }
+ Object timeObj = formData[timeControlIndex];
+ /*
+ * this should have found the time contol in the form of a string from the database.
+ * try to unpack it.
+ */
+ Long timeMillis = SQLTypes.millisFromTimeStamp(timeObj);
+
+ return timeMillis;
+ }
+
+ /**
+ * find a correctly set property value for the end time (if set).
+ * @return
+ */
+ public Long getSetEndTime() {
+ return findTimeValue(PropertyTypes.ENDTIME);
+ }
+
+ @Override
+ public long getEndTimeInMilliseconds() {
+ Long time = findTimeValue(PropertyTypes.ENDTIME);
+ if (time != null) {
+ return time;
+ }
+ return super.getEndTimeInMilliseconds();
+ }
+
+ @Override
+ public String getSummaryString() {
+ String str = String.format("%s", formDescription.getFormNiceName());
+ Object[] data = getFormData();
+ int iDat = 0;
+ for (ControlDescription cd:formDescription.getInputControlDescriptions()) {
+ if (data[iDat] == null) {
+ str += String.format("%s: -", cd.getTitle());
+ }
+ else {
+ str += String.format("
%s: %s", cd.getTitle(), data[iDat].toString());
+ }
+ iDat++;
+ }
+
+ str += "";
+ return str;
+ }
+
}
diff --git a/src/loggerForms/FormsDataUnitEditor.java b/src/loggerForms/FormsDataUnitEditor.java
index 9cbb8fbc..deea3dff 100644
--- a/src/loggerForms/FormsDataUnitEditor.java
+++ b/src/loggerForms/FormsDataUnitEditor.java
@@ -16,8 +16,6 @@ import PamUtils.PamCalendar;
public class FormsDataUnitEditor{
-
-
/**
* @param formDescription
* @param formsDataUnit
@@ -29,8 +27,6 @@ public class FormsDataUnitEditor{
JFrame frame=PamController.getInstance().getGuiFrameManager().getFrame(frameNo);
-
-
FormsDataUnit updatedData = FormsDataUnitEditDialog.showDialog(frame, formDescription, formsDataUnit);
if (updatedData != null) {
diff --git a/src/loggerForms/FormsLogging.java b/src/loggerForms/FormsLogging.java
index 64e0d8e6..e2c9c843 100644
--- a/src/loggerForms/FormsLogging.java
+++ b/src/loggerForms/FormsLogging.java
@@ -2,16 +2,20 @@ package loggerForms;
import java.util.ArrayList;
+import PamController.PamViewParameters;
import loggerForms.controlDescriptions.ControlDescription;
import loggerForms.controlDescriptions.InputControlDescription;
+import pamScrollSystem.ViewLoadObserver;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
+import generalDatabase.PamConnection;
+import generalDatabase.PamTableDefinition;
import generalDatabase.SQLLogging;
import generalDatabase.SQLTypes;
public class FormsLogging extends SQLLogging {
- FormDescription formDescription;
+ private FormDescription formDescription;
protected FormsLogging(FormDescription formDescription, PamDataBlock pamDataBlock) {
super(pamDataBlock);
@@ -20,53 +24,34 @@ public class FormsLogging extends SQLLogging {
setTableDefinition(formDescription.getOutputTableDef());
}
-// @Override
-// public void setTableData(PamDataUnit pamDataUnit) {
-//
-// FormsDataUnit formDataUnit = (FormsDataUnit) pamDataUnit;
-// int dataLen = formDataUnit.getFormData().length;
-// int tableLen= getTableDefinition().getTableItemCount();
-//
-//// for (int j=0;j inputCtrls = formDescription.getInputControlDescriptions();
InputControlDescription cd;
@@ -76,9 +61,6 @@ public class FormsLogging extends SQLLogging {
}
-// for (ControlDescription controlDescription:formDescription.getInputControlDescriptions()){
-// controlDescription.moveDataTo
-// }
}
/* (non-Javadoc)
@@ -98,21 +80,6 @@ public class FormsLogging extends SQLLogging {
}
}
-//
-// int dataLen = formDescription.getInputControlDescriptions().size();
-// int tableLen= getTableDefinition().getTableItemCount();
-// int diff = tableLen-dataLen;
-// Object[] formData = new Object[dataLen];
-// int tableIndex;
-// for (int j=0;j for now this is basically just disabling buttons if
* we're in viewer mode. A More sophisticated function
- * might consider enabling / diabling depending on whether
+ * might consider enabling / disabling depending on whether
* or not a form can be saved.
*/
public void enableControls() {
boolean isViewer = PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW;
- if (saveButton != null) saveButton.setEnabled(!isViewer);
- if (clearButton != null) clearButton.setEnabled(!isViewer);
- if (cancelButton != null) cancelButton.setEnabled(!isViewer);
+ boolean viewerEds = false;
+ if (formDescription != null) {
+ FormsControl formsControl = formDescription.getFormsControl();
+ viewerEds = formsControl.getFormsParameters().allowViewerChanges;
+ }
+ if (saveButton != null) {
+ saveButton.setEnabled(!isViewer || viewerEds);
+ if (isViewer) {
+ saveButton.setText(restoredDataUnit == null ? "Save" : "Update...");
+ }
+ }
+ if (clearButton != null) {
+ clearButton.setEnabled(!isViewer);
+ }
+ if (cancelButton != null) {
+ cancelButton.setEnabled(!isViewer);
+ }
}
class SaveButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand().equals("Save")) {
+// if (e.getActionCommand().equals("Save")) {
String er = getFormErrors();
getFormWarnings();
@@ -628,7 +645,7 @@ public class LoggerForm{
if (er==null){
save();
}
- }
+// }
}
}
@@ -636,17 +653,16 @@ public class LoggerForm{
@Override
public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand().equals("Save")) {
+// if (e.getActionCommand().equals("Save")) {
String er = getFormErrors();
getFormWarnings();
-
-
+
if (er==null){
save();
formDescription.removeSubtabform(loggerForm);
}
- }
+// }
}
}
@@ -737,9 +753,16 @@ public class LoggerForm{
* @param formsDataUnit
*/
void restoreData(FormsDataUnit formsDataUnit){
- // this.formsDataUnit = formsDataUnit;
- Object[] formData = formsDataUnit.getFormData();
- transferDataArrayToForm(formData);
+ restoredDataUnit = formsDataUnit;
+ if (formsDataUnit != null) {
+ // this.formsDataUnit = formsDataUnit;
+ Object[] formData = formsDataUnit.getFormData();
+ transferDataArrayToForm(formData);
+ }
+ else {
+ clear();
+ }
+ enableControls();
}
/**
@@ -840,14 +863,40 @@ public class LoggerForm{
* Extract and save teh data inot a new PAmDAtaUnit.
*/
private void save() {
- //create form data object v
+ //create form data object
Object[] formData = extractFormData();
+
+ boolean isViewer = PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW;
+ boolean isNew = true;
+ if (isViewer && restoredDataUnit != null) {
+ isNew = false;
+ }
- if (NewOrEdit==NewDataForm){
+ if (isNew){
FormsDataUnit formDataUnit = new FormsDataUnit(loggerForm,PamCalendar.getTimeInMillis(), formDescription, formData);
- // dU.setParentDataBlock(formDescription.getFormsDataBlock());
-// System.out.println(formDescription.getXMLData(formDataUnit));
formDescription.getFormsDataBlock().addPamData(formDataUnit);
+ // in viewer mode, will need to do something to get this to save.
+ if (isViewer) {
+ formDescription.getFormsDataBlock().getLogging().logData(DBControlUnit.findConnection(), formDataUnit);
+ formDescription.getFormsDataBlock().sortData();
+ }
+ }
+ else {
+ // update the data form. Ask first.
+ Frame win = formDescription.getFormsControl().getGuiFrame();
+ String msg = "Do you want to update this form with new data ?";
+ int ans = WarnOnce.showWarning(win, "Logger forms: " + formDescription.getFormName(), msg, WarnOnce.OK_CANCEL_OPTION);
+ if (ans == WarnOnce.OK_OPTION) {
+ if (restoredDataUnit == null) {
+ WarnOnce.showWarning(win, "Logger forms: " + formDescription.getFormName(), "No data to update", WarnOnce.WARNING_MESSAGE);
+ }
+ else {
+ restoredDataUnit.setFormsData(loggerForm, formData);
+ // should update database on next SaveData, but not before.
+ formDescription.getFormsDataBlock().updatePamData(restoredDataUnit, PamCalendar.getTimeInMillis());
+ formDescription.getFormsDataBlock().sortData();
+ }
+ }
}
// else if(NewOrEdit==EditDataForm && formsDataUnit != null){
// formsDataUnit.setFormsData(formData);
@@ -914,6 +963,9 @@ public class LoggerForm{
public JButton getSaveButton() {
return saveButton;
}
+ public void optionsChange() {
+ enableControls();
+ }
// public GpsData getOriginLatLong(FormsDataUnit formsDataUnit) {
// GpsData gps = getOrigin(GPSOriginSystem.class, formsDataUnit);
diff --git a/src/loggerForms/LoggerFormGraphics.java b/src/loggerForms/LoggerFormGraphics.java
index 57612663..7ad5759f 100644
--- a/src/loggerForms/LoggerFormGraphics.java
+++ b/src/loggerForms/LoggerFormGraphics.java
@@ -32,6 +32,7 @@ import PamView.PamSymbolType;
import PamView.PanelOverlayDraw;
import PamView.GeneralProjector.ParameterType;
import PamView.GeneralProjector.ParameterUnits;
+import PamView.symbol.PamSymbolChooser;
import PamView.symbol.SymbolData;
import PamguardMVC.PamDataUnit;
@@ -189,7 +190,7 @@ public class LoggerFormGraphics extends PanelOverlayDraw {
double shipCourse = plotOrigin.getCourseOverGround();
double shipHead = plotOrigin.getHeading();
- PamSymbol plotSymbol = getPlotSymbol(formDataUnit);
+ PamSymbol plotSymbol = getPlotSymbol(generalProjector, formDataUnit);
Coordinate3d detOrigin = generalProjector.getCoord3d(plotOrigin.getLatitude(), plotOrigin.getLongitude(), plotOrigin.getHeight());
// see if there is range heading and bearing data.
@@ -248,7 +249,7 @@ public class LoggerFormGraphics extends PanelOverlayDraw {
int nControls = data.length;
ControlDescription controlDescription;
ArrayList controlDescriptions = formDescription.getInputControlDescriptions();
- PamSymbol plotSymbol = getPlotSymbol(dataUnit);
+ PamSymbol plotSymbol = getPlotSymbol(generalProjector, dataUnit);
if (plotSymbol == null) {
return null;
}
@@ -354,7 +355,22 @@ public class LoggerFormGraphics extends PanelOverlayDraw {
* @param pamDataUnit data unit to plot
* @return symbol.
*/
- private PamSymbol getPlotSymbol(FormsDataUnit dataUnit) {
+ private PamSymbol getPlotSymbol(GeneralProjector projector, FormsDataUnit dataUnit) {
+ /**
+ * Try to use the new selector system. If it's not there, then revert to
+ * the older system.
+ */
+ PamSymbolChooser chooser = null;
+ if (projector != null) {
+ chooser = projector.getPamSymbolChooser();
+ }
+ if (chooser != null) {
+ PamSymbol chosenSymbol = chooser.getPamSymbol(projector, dataUnit);
+ if (chosenSymbol != null) {
+ return chosenSymbol;
+ }
+ }
+
/**
* first go through all the controls and see which is
* the first one that's initiated plotting. If it's
@@ -409,22 +425,7 @@ public class LoggerFormGraphics extends PanelOverlayDraw {
@Override
public String getHoverText(GeneralProjector generalProjector,
PamDataUnit dataUnit, int iSide) {
- FormsDataUnit formsDU = (FormsDataUnit) dataUnit;
- String str = String.format("%s", formDescription.getFormNiceName());
- Object[] data = formsDU.getFormData();
- int iDat = 0;
- for (ControlDescription cd:formDescription.getInputControlDescriptions()) {
- if (data[iDat] == null) {
- str += String.format("%s: -", cd.getTitle());
- }
- else {
- str += String.format("
%s: %s", cd.getTitle(), data[iDat].toString());
- }
- iDat++;
- }
-
- str += "";
- return str;
+ return dataUnit.getSummaryString();
}
private void createSymbols() {
diff --git a/src/loggerForms/PropertyTypes.java b/src/loggerForms/PropertyTypes.java
index b0a034f9..b473ee7a 100644
--- a/src/loggerForms/PropertyTypes.java
+++ b/src/loggerForms/PropertyTypes.java
@@ -1,7 +1,7 @@
package loggerForms;
public enum PropertyTypes {
- ORDER, AUTOALERT,SUBTABS,POPUP,HIDDEN,AUTORECORD,BEARING,
+ STARTTIME, ENDTIME, ORDER, AUTOALERT,SUBTABS,POPUP,HIDDEN,AUTORECORD,BEARING,
RANGE,HEADING,FONT,DBTABLENAME,
FORMCOLOUR,FORMCOLOR,
HOTKEY,NOCLEAR,NOCANCEL,NOTOFFLINE,NOTONLINE,
@@ -16,6 +16,10 @@ public enum PropertyTypes {
public String getDescription() {
switch (this) {
+ case STARTTIME:
+ return "Form start time. Will be used as main data UTC. If undefined, form time is save time";
+ case ENDTIME:
+ return "Form end time. Will be used data end time in period data";
case AUTOALERT:
return "A warning will be issued if the form has not been completed for a set time";
case AUTORECORD:
diff --git a/src/loggerForms/controlDescriptions/ControlDescription.java b/src/loggerForms/controlDescriptions/ControlDescription.java
index 85b780b9..80b34940 100644
--- a/src/loggerForms/controlDescriptions/ControlDescription.java
+++ b/src/loggerForms/controlDescriptions/ControlDescription.java
@@ -3,8 +3,6 @@
*/
package loggerForms.controlDescriptions;
-import generalDatabase.EmptyTableDefinition;
-
import java.sql.Types;
import javax.swing.JPanel;
@@ -12,7 +10,6 @@ import javax.swing.JPanel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import PamUtils.XMLUtils;
import loggerForms.FormDescription;
import loggerForms.FormsDataUnit;
import loggerForms.FormsTableItem;
@@ -37,7 +34,6 @@ public abstract class ControlDescription extends ItemDescription {
protected ControlDescription(FormDescription formDescription, ItemInformation itemInformation) {
super(formDescription, itemInformation);
eType = ControlTypes.valueOf(getType());
-// System.out.println(getType()+";"+eType.toString());
}
@@ -88,11 +84,6 @@ public abstract class ControlDescription extends ItemDescription {
return formsTableItems;
}
-
-
-
-
-
private ControlTypes eType;
/**
diff --git a/src/loggerForms/effort/FormsEffortUnit.java b/src/loggerForms/effort/FormsEffortUnit.java
new file mode 100644
index 00000000..294218cb
--- /dev/null
+++ b/src/loggerForms/effort/FormsEffortUnit.java
@@ -0,0 +1,15 @@
+package loggerForms.effort;
+
+import effort.EffortDataUnit;
+import loggerForms.FormsDataUnit;
+
+public class FormsEffortUnit extends EffortDataUnit {
+
+ private FormsDataUnit parentFormUnit;
+
+ public FormsEffortUnit(LoggerEffortProvider loggerEffortProvider, FormsDataUnit parentFormUnit, long formEndTime) {
+ super(loggerEffortProvider, parentFormUnit, parentFormUnit.getTimeMilliseconds(), formEndTime);
+ this.parentFormUnit = parentFormUnit;
+ }
+
+}
diff --git a/src/loggerForms/effort/LoggerEffortProvider.java b/src/loggerForms/effort/LoggerEffortProvider.java
new file mode 100644
index 00000000..0cf79889
--- /dev/null
+++ b/src/loggerForms/effort/LoggerEffortProvider.java
@@ -0,0 +1,165 @@
+package loggerForms.effort;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+import PamController.PamController;
+import PamView.symbol.PamSymbolManager;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import PamguardMVC.dataSelector.DataSelector;
+import dataMap.OfflineDataMap;
+import effort.EffortDataUnit;
+import effort.EffortProvider;
+import loggerForms.FormDescription;
+import loggerForms.FormsDataBlock;
+import loggerForms.FormsDataUnit;
+
+public class LoggerEffortProvider extends EffortProvider {
+
+ private FormsDataBlock formsDataBlock;
+
+ private ArrayList onlineEffort;
+
+ public LoggerEffortProvider(FormsDataBlock parentDataBlock) {
+ super(parentDataBlock);
+ this.formsDataBlock = parentDataBlock;
+ FormDescription formsDescription = parentDataBlock.getFormDescription();
+ }
+
+// @Override
+// public EffortDataUnit getEffort(long timeMilliseconds) {
+// ListIterator iterator = formsDataBlock.getListIterator(timeMilliseconds, 0, PamDataBlock.MATCH_BEFORE, PamDataBlock.POSITION_BEFORE);
+// FormsDataUnit currentUnit = null;
+// FormsDataUnit nextUnit = null;
+// if (iterator == null) {
+// return null;
+// }
+//
+// if (iterator.hasNext()) {
+// currentUnit = iterator.next();
+// }
+// if (iterator.hasNext()) {
+// nextUnit = iterator.next();
+// }
+// if (currentUnit == null) {
+// return null;
+// }
+// long endTime = getEndTime(currentUnit, nextUnit);
+//
+// return new FormsEffortUnit(this, currentUnit, endTime);
+// }
+
+ private long getEndTime(FormsDataUnit currentUnit, FormsDataUnit nextUnit) {
+ Long end = currentUnit.getSetEndTime();
+ if (end != null) {
+ return end;
+ }
+ if (nextUnit == null) {
+ return getLastDatasetTime();
+ }
+ else {
+ return nextUnit.getTimeMilliseconds();
+ }
+ }
+
+ @Override
+ public List getAllEffortThings() {
+ return onlineEffort;
+ }
+
+ @Override
+ public void viewerLoadData() {
+ ArrayList allList = new ArrayList();
+ ListIterator iterator = formsDataBlock.getListIterator(0);
+ FormsDataUnit currentUnit = null;
+ FormsDataUnit nextUnit = null;
+ if (iterator.hasNext()) {
+ currentUnit = iterator.next();
+ }
+ while (iterator.hasNext()) {
+ nextUnit = iterator.next();
+ long end = getEndTime(currentUnit, nextUnit);
+ allList.add(new FormsEffortUnit(this, currentUnit, end));
+ currentUnit = nextUnit;
+ }
+ if (currentUnit != null) {
+ long end = getEndTime(currentUnit, null);
+ allList.add(new FormsEffortUnit(this, currentUnit, end));
+ }
+ onlineEffort = allList;
+ }
+
+ @Override
+ public DataSelector getDataSelector(String selectorName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public PamSymbolManager getSymbolManager() {
+ return formsDataBlock.getPamSymbolManager();
+ }
+
+ /**
+ * Get the last time of any data in this dataset from any data map.
+ * @return
+ */
+ private long getLastDatasetTime() {
+ long lastTime = Long.MIN_VALUE;
+ ArrayList allData = PamController.getInstance().getDataBlocks();
+ for (PamDataBlock aBlock : allData) {
+ OfflineDataMap dataMap = aBlock.getPrimaryDataMap();
+ if (dataMap != null) {
+ lastTime = Math.max(lastTime, dataMap.getLastDataTime());
+ }
+ }
+
+ return lastTime;
+ }
+
+ @Override
+ public String getName() {
+ return formsDataBlock.getDataName();
+ }
+
+ @Override
+ public void realTimeStart(long timeMilliseconds) {
+ // Don't do anything with start and end of processing
+ }
+
+ @Override
+ public void realTimeStop(long timeMilliseconds) {
+ // Don't do anything with start and end of processing
+ }
+
+ @Override
+ public void newData(PamDataUnit pamDataUnit) {
+ // generate effort things from incoming form data.
+ if (onlineEffort == null) {
+ onlineEffort = new ArrayList<>();
+ }
+ FormsEffortUnit lastEffort = null;
+ if (onlineEffort.size() > 0) {
+ lastEffort = (FormsEffortUnit) onlineEffort.get(onlineEffort.size()-1);
+ }
+ FormsDataUnit formDataUnit = (FormsDataUnit) pamDataUnit;
+ long thisStart = formDataUnit.getTimeMilliseconds();
+ Long thisEnd = formDataUnit.getSetEndTime();
+ if (lastEffort != null) {
+ /*
+ * If the previous effort didn't have a end time, then use this start as that's end.
+ */
+ if (lastEffort.getEffortEnd() >= EffortDataUnit.ONGOINGEFFORT/2) {
+ lastEffort.setEffortEnd(thisStart);
+ }
+ }
+ if (thisEnd == null) {
+ thisEnd = EffortDataUnit.ONGOINGEFFORT;
+ }
+ FormsEffortUnit newEffort = new FormsEffortUnit(this, formDataUnit, thisEnd);
+ onlineEffort.add(newEffort);
+ }
+
+}
diff --git a/src/loggerForms/formdesign/FormEditor.java b/src/loggerForms/formdesign/FormEditor.java
index 35df6d9b..4bc49adf 100644
--- a/src/loggerForms/formdesign/FormEditor.java
+++ b/src/loggerForms/formdesign/FormEditor.java
@@ -11,6 +11,7 @@ import loggerForms.ItemInformation;
import loggerForms.PropertyDescription;
import loggerForms.PropertyTypes;
import loggerForms.UDColName;
+import loggerForms.controlDescriptions.ControlTypes;
import loggerForms.formdesign.propertypanels.AutoAlertPanel;
import loggerForms.formdesign.propertypanels.BearingPanel;
import loggerForms.formdesign.propertypanels.BooleanPanel;
@@ -26,6 +27,7 @@ import loggerForms.formdesign.propertypanels.PropertyPanel;
import loggerForms.formdesign.propertypanels.RangePanel;
import loggerForms.formdesign.propertypanels.SymbolPanel;
import loggerForms.formdesign.propertypanels.TextPanel;
+import loggerForms.formdesign.propertypanels.XReferencePanel;
/**
* Layer that sits between the form description and the actual edit
@@ -154,6 +156,10 @@ public class FormEditor {
public PropertyPanel makePropertyPanel(PropertyTypes propertyType) {
switch (propertyType) {
+ case STARTTIME:
+ return new XReferencePanel(this, propertyType, ControlTypes.TIMESTAMP);
+ case ENDTIME:
+ return new XReferencePanel(this, propertyType, ControlTypes.TIMESTAMP);
case AUTOALERT:
return new IntegerPanel(this, propertyType, UDColName.AutoUpdate, "Alert operator every", "minutes");
case AUTORECORD:
diff --git a/src/loggerForms/formdesign/propertypanels/XReferencePanel.java b/src/loggerForms/formdesign/propertypanels/XReferencePanel.java
new file mode 100644
index 00000000..84ec28f4
--- /dev/null
+++ b/src/loggerForms/formdesign/propertypanels/XReferencePanel.java
@@ -0,0 +1,95 @@
+package loggerForms.formdesign.propertypanels;
+
+import java.util.ArrayList;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+
+import loggerForms.ItemInformation;
+import loggerForms.PropertyTypes;
+import loggerForms.UDColName;
+import loggerForms.controlDescriptions.ControlTypes;
+import loggerForms.formdesign.ControlTitle;
+import loggerForms.formdesign.FormEditor;
+import loggerForms.formdesign.FormEditor.EditNotify;
+
+/**
+ * Property form for a cross reference sontrol.
+ * @author dg50
+ *
+ */
+public class XReferencePanel extends PropertyPanel {
+
+ private ControlTypes controlType;
+
+ private JComboBox fieldNames;
+
+ public XReferencePanel(FormEditor formEditor, PropertyTypes propertyType, ControlTypes controlType) {
+ super(formEditor, propertyType);
+ this.controlType = controlType;
+ addItem(new JLabel(" Use "));
+ addItem(fieldNames = new JComboBox());
+ }
+ /* (non-Javadoc)
+ * @see loggerForms.formdesign.propertypanels.PropertyPanel#notifyChanges(loggerForms.formdesign.FormEditor.EditNotify)
+ */
+ @Override
+ public void notifyChanges(EditNotify notifyType) {
+ fillComboBox();
+ }
+
+ /**
+ * Fill the combo box with a list of all control names that have
+ * numeric data which might be used for bearing information.
+ */
+ private void fillComboBox() {
+ String currentValue = (String) fieldNames.getSelectedItem();
+ fieldNames.removeAllItems();
+ ArrayList ctrlTitles = formEditor.getControlTitles();
+ for (ControlTitle title:ctrlTitles) {
+ if (title.getType() == null) {
+ continue;
+ }
+ if (title.getType() == controlType) {
+ fieldNames.addItem(title.getItemInformation().getStringProperty(UDColName.Title.toString()));
+ }
+ }
+ if (currentValue != null) {
+ fieldNames.setSelectedItem(currentValue);
+ }
+ else {
+// pushProperty();
+ }
+ }
+
+ @Override
+ public void propertyEnable(boolean enabled) {
+ fieldNames.setEnabled(enabled);
+ }
+
+ @Override
+ public void pushProperty(ItemInformation itemInformation) {
+ super.pushProperty(itemInformation);
+ if (itemInformation == null) {
+ return;
+ }
+ try {
+ fieldNames.setSelectedItem(itemInformation.getStringProperty(UDColName.Title.toString()));
+ }
+ catch (Exception e) {};
+ }
+
+ @Override
+ public ItemInformation fetchProperty(ItemInformation itemInformation) {
+ itemInformation = super.fetchProperty(itemInformation);
+ if (itemInformation == null) {
+ return null;
+ }
+
+ itemInformation.setProperty(UDColName.Title.toString(), fieldNames.getSelectedItem());
+
+ return itemInformation;
+ }
+
+
+}
diff --git a/src/loggerForms/symbol/IntegerSymbolModifier.java b/src/loggerForms/symbol/IntegerSymbolModifier.java
new file mode 100644
index 00000000..03cbec8d
--- /dev/null
+++ b/src/loggerForms/symbol/IntegerSymbolModifier.java
@@ -0,0 +1,53 @@
+package loggerForms.symbol;
+
+import java.awt.Color;
+
+import PamView.GeneralProjector;
+import PamView.PamColors;
+import PamView.PamSymbolType;
+import PamView.symbol.PamSymbolChooser;
+import PamView.symbol.SymbolData;
+import PamguardMVC.PamDataUnit;
+import loggerForms.FormDescription;
+import loggerForms.controlDescriptions.ControlDescription;
+
+/**
+ * Integer symbol modifier. Basically returns the whale colour rotation.
+ * @author dg50
+ *
+ */
+public class IntegerSymbolModifier extends LoggerSymbolModifier {
+
+ public IntegerSymbolModifier(FormDescription formDescription, ControlDescription controlDescription,
+ PamSymbolChooser symbolChooser, int modifyableBits) {
+ super(formDescription, controlDescription, symbolChooser, modifyableBits);
+ }
+
+ @Override
+ public SymbolData getSymbolData(GeneralProjector projector, PamDataUnit dataUnit) {
+ Object data = getControlData(dataUnit);
+ if (data == null) {
+ return null;
+ }
+ int number = 0;
+ if (data instanceof String) {
+ try {
+ number = Integer.valueOf(data.toString());
+ }
+ catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ if (data instanceof Number) {
+ try {
+ number = Integer.valueOf(data.toString());
+ }
+ catch (Exception e) {
+ return null;
+ }
+ }
+ Color col = PamColors.getInstance().getChannelColor(number);
+ return new SymbolData(PamSymbolType.SYMBOL_CIRCLE, 1, 1, true, col, col);
+ }
+
+}
diff --git a/src/loggerForms/symbol/LoggerSymbolChooser.java b/src/loggerForms/symbol/LoggerSymbolChooser.java
new file mode 100644
index 00000000..d25e05bc
--- /dev/null
+++ b/src/loggerForms/symbol/LoggerSymbolChooser.java
@@ -0,0 +1,23 @@
+package loggerForms.symbol;
+
+import PamView.GeneralProjector;
+import PamView.symbol.StandardSymbolChooser;
+import PamView.symbol.StandardSymbolManager;
+import PamView.symbol.SymbolData;
+import PamguardMVC.PamDataBlock;
+import dataPlots.data.SimpleSymbolChooser;
+import loggerForms.FormsDataBlock;
+
+public class LoggerSymbolChooser extends StandardSymbolChooser {
+
+ private FormsDataBlock formsDataBlock;
+
+ public LoggerSymbolChooser(StandardSymbolManager standardSymbolManager, FormsDataBlock pamDataBlock,
+ String displayName, SymbolData defaultSymbol, GeneralProjector projector) {
+ super(standardSymbolManager, pamDataBlock, displayName, defaultSymbol, projector);
+ this.formsDataBlock = pamDataBlock;
+
+ }
+
+
+}
diff --git a/src/loggerForms/symbol/LoggerSymbolManager.java b/src/loggerForms/symbol/LoggerSymbolManager.java
new file mode 100644
index 00000000..b39ee650
--- /dev/null
+++ b/src/loggerForms/symbol/LoggerSymbolManager.java
@@ -0,0 +1,130 @@
+package loggerForms.symbol;
+
+import PamView.GeneralProjector;
+import PamView.PamSymbol;
+import PamView.symbol.PamSymbolChooser;
+import PamView.symbol.PamSymbolManager;
+import PamView.symbol.StandardSymbolChooser;
+import PamView.symbol.StandardSymbolManager;
+import PamView.symbol.SymbolData;
+import PamView.symbol.modifier.SymbolModType;
+import PamguardMVC.PamDataBlock;
+import loggerForms.FormDescription;
+import loggerForms.FormsDataBlock;
+import loggerForms.LoggerFormGraphics;
+import loggerForms.PropertyDescription;
+import loggerForms.PropertyTypes;
+import loggerForms.controlDescriptions.ControlDescription;
+import loggerForms.formdesign.FormList;
+import loggerForms.formdesign.propertypanels.SymbolPanel;
+
+public class LoggerSymbolManager extends StandardSymbolManager {
+
+ private FormsDataBlock formsDataBlock;
+ private SymbolData standardFormSymbol;
+
+ public LoggerSymbolManager(FormsDataBlock pamDataBlock) {
+ super(pamDataBlock, LoggerFormGraphics.defaultSymbol);
+ this.formsDataBlock = pamDataBlock;
+ }
+
+ @Override
+ protected LoggerSymbolChooser createSymbolChooser(String displayName, GeneralProjector projector) {
+ return new LoggerSymbolChooser(this, formsDataBlock, displayName, getDefaultSymbol(), projector);
+ }
+
+ @Override
+ public SymbolData getDefaultSymbol() {
+ /**
+ * the default default is a generic one for logger data. See if it is overridden by a symbol
+ * specified for the form.
+ */
+ SymbolData formSymbol = getFormSymbol();
+ if (formSymbol != null) {
+ return formSymbol;
+ }
+ else {
+ return super.getDefaultSymbol();
+ }
+ }
+
+ /**
+ * Get the default symbol for the form. Might be null,
+ * though might have been set in the form properties.
+ * @return
+ */
+ public SymbolData getFormSymbol() {
+ if (standardFormSymbol == null) {
+ FormDescription formDescription = formsDataBlock.getFormDescription();
+ PropertyDescription formProperty = formDescription.findProperty(PropertyTypes.SYMBOLTYPE);
+ if (formProperty == null) {
+ return null;
+ }
+ PamSymbol symbol = SymbolPanel.createSymbol(formProperty.getItemInformation());
+ if (symbol != null) {
+ standardFormSymbol = symbol.getSymbolData();
+ }
+ }
+ return standardFormSymbol;
+ }
+
+ @Override
+ public void addSymbolModifiers(PamSymbolChooser psc) {
+ // probably don't want the standard ones.
+// super.addSymbolModifiers(psc);
+ /*
+ * now add symbol modifiers for each control in the form.
+ * This will primarily be lookups which should have defined colours.
+ * May be able to do other controls based on their type / null / >0 values.
+ * Focus on lut's for now.
+ */
+ FormDescription formDescription = formsDataBlock.getFormDescription();
+ FormList ctrls = formDescription.getControlDescriptions();
+ for (ControlDescription ctrlDescription : ctrls) {
+ LoggerSymbolModifier modifier = createSymbolModifier(formDescription, ctrlDescription, psc);
+ if (modifier != null) {
+ psc.addSymbolModifier(modifier);
+ }
+ }
+ }
+
+ private LoggerSymbolModifier createSymbolModifier(FormDescription formDescription,
+ ControlDescription ctrlDescription, PamSymbolChooser psc) {
+ switch (ctrlDescription.getEType()) {
+ case CHAR:
+ break;
+ case CHECKBOX:
+ break;
+ case COUNTER:
+ return new IntegerSymbolModifier(formDescription, ctrlDescription, psc, SymbolModType.FILLCOLOUR | SymbolModType.LINECOLOUR);
+ case DOUBLE:
+ break;
+ case INTEGER:
+ return new IntegerSymbolModifier(formDescription, ctrlDescription, psc, SymbolModType.FILLCOLOUR | SymbolModType.LINECOLOUR);
+ case LATLONG:
+ break;
+ case LOOKUP:
+ return new LookupSymbolModifier(formDescription, ctrlDescription, psc, SymbolModType.EVERYTHING);
+ case NMEACHAR:
+ break;
+ case NMEAFLOAT:
+ break;
+ case NMEAINT:
+ break;
+ case SHORT:
+ return new IntegerSymbolModifier(formDescription, ctrlDescription, psc, SymbolModType.FILLCOLOUR | SymbolModType.LINECOLOUR);
+ case SINGLE:
+ break;
+ case STATIC:
+ break;
+ case TIME:
+ break;
+ case TIMESTAMP:
+ break;
+ default:
+ break;
+
+ }
+ return null;
+ }
+}
diff --git a/src/loggerForms/symbol/LoggerSymbolModifier.java b/src/loggerForms/symbol/LoggerSymbolModifier.java
new file mode 100644
index 00000000..5a31e3a4
--- /dev/null
+++ b/src/loggerForms/symbol/LoggerSymbolModifier.java
@@ -0,0 +1,66 @@
+package loggerForms.symbol;
+
+import PamView.GeneralProjector;
+import PamView.symbol.PamSymbolChooser;
+import PamView.symbol.SymbolData;
+import PamView.symbol.modifier.SymbolModifier;
+import PamguardMVC.PamDataUnit;
+import loggerForms.FormDescription;
+import loggerForms.FormsDataUnit;
+import loggerForms.controlDescriptions.ControlDescription;
+
+abstract public class LoggerSymbolModifier extends SymbolModifier {
+
+ protected FormDescription formDescription;
+ protected ControlDescription controlDescription;
+ protected int controlIndex;
+
+ public LoggerSymbolModifier(FormDescription formDescription, ControlDescription controlDescription,
+ PamSymbolChooser symbolChooser, int modifyableBits) {
+ super(controlDescription.getTitle(), symbolChooser, modifyableBits);
+ this.formDescription = formDescription;
+ this.controlDescription = controlDescription;
+ controlIndex = formDescription.getControlIndex(controlDescription);
+ }
+
+ /**
+ * Get the data object for this control from the data unit.
+ * @param dataUnit
+ * @return
+ */
+ public Object getControlData(PamDataUnit dataUnit) {
+ if (dataUnit instanceof FormsDataUnit == false) {
+ return null;
+ }
+ FormsDataUnit formDataUnit = (FormsDataUnit) dataUnit;
+ Object[] data = formDataUnit.getFormData();
+ if (data == null || data.length <= controlIndex || controlIndex < 0) {
+ return null;
+ }
+ return data[controlIndex];
+ }
+
+
+ /**
+ * @return the formDescription
+ */
+ protected FormDescription getFormDescription() {
+ return formDescription;
+ }
+
+ /**
+ * @return the controlDescription
+ */
+ protected ControlDescription getControlDescription() {
+ return controlDescription;
+ }
+
+ /**
+ * @return the controlIndex
+ */
+ protected int getControlIndex() {
+ return controlIndex;
+ }
+
+
+}
diff --git a/src/loggerForms/symbol/LookupSymbolModifier.java b/src/loggerForms/symbol/LookupSymbolModifier.java
new file mode 100644
index 00000000..64d12a46
--- /dev/null
+++ b/src/loggerForms/symbol/LookupSymbolModifier.java
@@ -0,0 +1,42 @@
+package loggerForms.symbol;
+
+import PamView.GeneralProjector;
+import PamView.PamSymbol;
+import PamView.symbol.PamSymbolChooser;
+import PamView.symbol.SymbolData;
+import PamguardMVC.PamDataUnit;
+import generalDatabase.lookupTables.LookupItem;
+import generalDatabase.lookupTables.LookupList;
+import loggerForms.FormDescription;
+import loggerForms.FormsDataUnit;
+import loggerForms.controlDescriptions.CdLookup;
+import loggerForms.controlDescriptions.ControlDescription;
+
+public class LookupSymbolModifier extends LoggerSymbolModifier {
+
+ public LookupSymbolModifier(FormDescription formDescription, ControlDescription controlDescription,
+ PamSymbolChooser symbolChooser, int modifyableBits) {
+ super(formDescription, controlDescription, symbolChooser, modifyableBits);
+ }
+
+ @Override
+ public SymbolData getSymbolData(GeneralProjector projector, PamDataUnit dataUnit) {
+ Object data = getControlData(dataUnit);
+ if (data == null) {
+ return null;
+ }
+
+ LookupList lutList = ((CdLookup)controlDescription).getLookupList();
+ int lutIndex = lutList.indexOfCode(data.toString());
+ LookupItem lutItem = lutList.getLookupItem(lutIndex);
+ if (lutItem == null) {
+ return null;
+ }
+ PamSymbol symbol = lutItem.getSymbol();
+ if (symbol == null) {
+ return null;
+ }
+ return symbol.getSymbolData();
+ }
+
+}
diff --git a/src/ravendata/RavenControl.java b/src/ravendata/RavenControl.java
new file mode 100644
index 00000000..7769770d
--- /dev/null
+++ b/src/ravendata/RavenControl.java
@@ -0,0 +1,103 @@
+package ravendata;
+
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import javax.swing.JMenuItem;
+
+import Acquisition.AcquisitionControl;
+import PamController.InputStoreInfo;
+import PamController.PamConfiguration;
+import PamController.PamControlledUnit;
+import PamController.PamControlledUnitSettings;
+import PamController.PamController;
+import PamController.PamSettingManager;
+import PamController.PamSettings;
+import PamView.dialog.warn.WarnOnce;
+import pamViewFX.PamSettingsMenuPane;
+import ravendata.swing.RavenImportDialog;
+
+/**
+ * System for importing and displaying data from Raven selection tables.
+ * @author dg50
+ *
+ */
+public class RavenControl extends PamControlledUnit implements PamSettings {
+
+ private RavenProcess ravenProcess;
+
+ private static final String unitType = "Raven Import";
+ public static final String defaultName = unitType;
+
+ private RavenParameters ravenParameters = new RavenParameters();
+
+ public RavenControl(String unitName) {
+ super(unitType, unitName);
+ this.ravenProcess = new RavenProcess(this);
+ addPamProcess(ravenProcess);
+ PamSettingManager.getInstance().registerSettings(this);
+ }
+
+ public RavenControl(PamConfiguration pamConfiguration, String unitType, String unitName) {
+ super(pamConfiguration, unitType, unitName);
+ }
+
+ @Override
+ public JMenuItem createDetectionMenu(Frame parentFrame) {
+ JMenuItem menuItem = new JMenuItem("Import Raven data ...");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ importData(parentFrame);
+ }
+ });
+ return menuItem;
+ }
+
+ protected void importData(Frame parentFrame) {
+ RavenParameters newParams = RavenImportDialog.showDialog(parentFrame, ravenParameters);
+ if (newParams == null) {
+ return;
+ }
+ ravenParameters = newParams;
+ // import the data. 1. Check for existing and delete, 2. Import, 3. rebuild datamap, 4. load data
+ RavenFileReader fileReader = null;
+ ArrayList ravenData = null;
+ try {
+ fileReader = new RavenFileReader(this, ravenParameters.importFile);
+ ravenData = fileReader.readTable();
+
+ fileReader.closeFile();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return;
+ }
+ if (ravenData != null) {
+ ravenProcess.createPAMGuardData(fileReader, ravenData);
+ }
+ }
+
+
+
+ @Override
+ public Serializable getSettingsReference() {
+ return ravenParameters;
+ }
+
+ @Override
+ public long getSettingsVersion() {
+ return RavenParameters.serialVersionUID;
+ }
+
+ @Override
+ public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
+ ravenParameters = (RavenParameters) pamControlledUnitSettings.getSettings();
+ return true;
+ }
+
+}
diff --git a/src/ravendata/RavenDataBlock.java b/src/ravendata/RavenDataBlock.java
new file mode 100644
index 00000000..8fe3f9c5
--- /dev/null
+++ b/src/ravendata/RavenDataBlock.java
@@ -0,0 +1,16 @@
+package ravendata;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamProcess;
+
+public class RavenDataBlock extends PamDataBlock {
+
+ private RavenProcess ravenProcess;
+
+ public RavenDataBlock(RavenProcess parentProcess, int channelMap) {
+ super(RavenDataUnit.class, "Selection", parentProcess, channelMap);
+ this.ravenProcess = parentProcess;
+ }
+
+
+}
diff --git a/src/ravendata/RavenDataRow.java b/src/ravendata/RavenDataRow.java
new file mode 100644
index 00000000..0e77da18
--- /dev/null
+++ b/src/ravendata/RavenDataRow.java
@@ -0,0 +1,159 @@
+package ravendata;
+
+public class RavenDataRow {
+
+ private int iRow;
+ private String[] data;
+ private Integer selection;
+ private String view;
+ private Integer channel;
+ private double beginT;
+ private double endT;
+ private double f1;
+ private double f2;
+ private int[] dataIndexes;
+ private boolean unpackOK;
+
+ // data on a row of raven data from a table.
+ public RavenDataRow(int iRow, String[] data, int[] dataIndexes) {
+ this.iRow = iRow;
+ this.data = data;
+ this.dataIndexes = dataIndexes;
+ unpackOK = unpackRow(dataIndexes);
+ }
+
+ /**
+ * @return the iRow
+ */
+ protected int getiRow() {
+ return iRow;
+ }
+
+ /**
+ * @return the data
+ */
+ protected String[] getData() {
+ return data;
+ }
+
+ /**
+ * Get a String value from the given column.
+ * @param iCol
+ * @return
+ */
+ public String getString(int iCol) {
+ return data[iCol];
+ }
+
+ /**
+ * Read an Integer value from the given column.
+ * @param iCol
+ * @return
+ */
+ public Integer getInteger(int iCol) {
+ try {
+ return Integer.valueOf(data[iCol]);
+ }
+ catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ /**
+ * Read a double value from the given column.
+ * @param iCol
+ * @return
+ */
+ public Double getDouble(int iCol) {
+ try {
+ return Double.valueOf(data[iCol]);
+ }
+ catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Unpack the row into more useful columns using the column indexes.
+ * @param mainIndexes
+ * @return
+ */
+ private boolean unpackRow(int[] mainIndexes) {
+ try {
+ selection = getInteger(mainIndexes[0]);
+ view = getString(mainIndexes[1]);
+ channel = getInteger(mainIndexes[2]);
+ beginT = getDouble(mainIndexes[3]);
+ endT = getDouble(mainIndexes[4]);
+ f1 = getDouble(mainIndexes[5]);
+ f2 = getDouble(mainIndexes[6]);
+ }
+ catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return the selection
+ */
+ protected Integer getSelection() {
+ return selection;
+ }
+
+ /**
+ * @return the view
+ */
+ protected String getView() {
+ return view;
+ }
+
+ /**
+ * @return the channel
+ */
+ protected Integer getChannel() {
+ return channel;
+ }
+
+ /**
+ * @return the beginT
+ */
+ protected double getBeginT() {
+ return beginT;
+ }
+
+ /**
+ * @return the endT
+ */
+ protected double getEndT() {
+ return endT;
+ }
+
+ /**
+ * @return the f1
+ */
+ protected double getF1() {
+ return f1;
+ }
+
+ /**
+ * @return the f2
+ */
+ protected double getF2() {
+ return f2;
+ }
+
+ /**
+ * @return the dataIndexes
+ */
+ protected int[] getDataIndexes() {
+ return dataIndexes;
+ }
+
+ /**
+ * @return the unpackOK
+ */
+ protected boolean isUnpackOK() {
+ return unpackOK;
+ }
+
+}
diff --git a/src/ravendata/RavenDataUnit.java b/src/ravendata/RavenDataUnit.java
new file mode 100644
index 00000000..49929ccf
--- /dev/null
+++ b/src/ravendata/RavenDataUnit.java
@@ -0,0 +1,20 @@
+package ravendata;
+
+import PamDetection.PamDetection;
+import PamguardMVC.AcousticDataUnit;
+import PamguardMVC.DataUnitBaseData;
+import PamguardMVC.PamDataUnit;
+
+public class RavenDataUnit extends PamDataUnit implements AcousticDataUnit, PamDetection {
+
+ public RavenDataUnit(long timeMilliseconds, int channelMap, long durationMillis, double f1, double f2) {
+ super(timeMilliseconds);
+ setChannelBitmap(channelMap);
+ setDurationInMilliseconds(durationMillis);
+ double[] freq = {f1, f2};
+ setFrequency(freq);
+ }
+
+
+
+}
diff --git a/src/ravendata/RavenFileReader.java b/src/ravendata/RavenFileReader.java
new file mode 100644
index 00000000..f18e8eb0
--- /dev/null
+++ b/src/ravendata/RavenFileReader.java
@@ -0,0 +1,101 @@
+package ravendata;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class RavenFileReader {
+
+ private RavenControl ravenControl;
+ private File ravenFile;
+ private ArrayList columnNames;
+ private BufferedReader fileReader;
+
+ private static String[] standardColumns = {"Selection", "View", "Channel", "Begin Time (s)", "End Time (s)", "Low Freq (Hz)", "High Freq (Hz)"};
+// private static String[] otherColumns = {"Selection", "View", "Channel", "Begin Time (s)", "End Time (s)", "end", "Low Freq (Hz)", "High Freq (Hz)",
+// "Begin File", "Delta Time (s)", "File Offset (s)", "Occupancy", "Manual Review", "Notes", "SongNumber"};
+ /*
+ * Sometimes some names appear in different places. Bugger.
+ * so need to find the index of each of the main columns we want.
+ */
+ private int[] mainIndexes;
+private int columnErrors;
+
+
+ public RavenFileReader(RavenControl ravenControl, String ravenFile) throws IOException {
+ this.ravenControl = ravenControl;
+ this.ravenFile = new File(ravenFile);
+ openFile();
+ }
+
+ public void closeFile() throws IOException {
+ if (fileReader != null) {
+ fileReader.close();
+ }
+ }
+
+ /**
+ * open the file, read the file header and get a list of column names.
+ * @throws IOException
+ */
+ private void openFile() throws IOException {
+ fileReader = new BufferedReader(new FileReader(ravenFile));
+ String firstLine = fileReader.readLine();
+ if (firstLine == null) {
+ throw new IOException("Empty file");
+ }
+ String[] cols = firstLine.split("\t");
+ columnNames = new ArrayList<>();
+ for (int i = 0; i < cols.length; i++) {
+ columnNames.add(cols[i]);
+ }
+ checkColumnNames();
+ }
+
+ public ArrayList readTable() throws IOException {
+ ArrayList allData = new ArrayList();
+ int iRow = 0;
+ while(true) {
+ String aLine = fileReader.readLine();
+ if (aLine == null) {
+ break;
+ }
+ String[] split = aLine.split("\t");
+ RavenDataRow aRow = new RavenDataRow(iRow++, split, mainIndexes);
+ allData.add(aRow);
+ }
+ return allData;
+ }
+
+ /**
+ * Check we have the correct standard columns.
+ */
+ private int checkColumnNames() {
+ mainIndexes = new int[standardColumns.length];
+ columnErrors = 0;
+ for (int i = 0; i < standardColumns.length; i++) {
+ mainIndexes[i] = columnNames.indexOf(standardColumns[i]);
+ if (mainIndexes[i] < 0) {
+ System.out.printf("Raven error: Unable to find column \"%s\" in data table\n", standardColumns[i]);
+ columnErrors++;
+ }
+ }
+ return columnErrors;
+ }
+
+ public boolean exists() {
+ return ravenFile.exists();
+ }
+
+ /**
+ * get a count of column errors.
+ * @return the columnErrors
+ */
+ protected int getColumnErrors() {
+ return columnErrors;
+ }
+
+}
diff --git a/src/ravendata/RavenLogging.java b/src/ravendata/RavenLogging.java
new file mode 100644
index 00000000..fab6c7de
--- /dev/null
+++ b/src/ravendata/RavenLogging.java
@@ -0,0 +1,30 @@
+package ravendata;
+
+import PamDetection.AcousticSQLLogging;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import generalDatabase.PamTableItem;
+import generalDatabase.SQLLogging;
+import generalDatabase.SQLTypes;
+
+public class RavenLogging extends AcousticSQLLogging {
+
+ private RavenDataBlock ravenDataBlock;
+ private RavenControl ravenControl;
+
+ private PamTableItem f1;
+
+ public RavenLogging(RavenControl ravenControl, RavenDataBlock pamDataBlock) {
+ super(pamDataBlock, ravenControl.getUnitName());
+ this.ravenControl = ravenControl;
+ this.ravenDataBlock = pamDataBlock;
+ }
+
+ @Override
+ protected PamDataUnit createDataUnit(SQLTypes sqlTypes, long timeMilliseconds, int chanMap, long duration,
+ double[] f) {
+ return new RavenDataUnit(timeMilliseconds, chanMap, duration, f[0], f[1]);
+ }
+
+
+}
diff --git a/src/ravendata/RavenParameters.java b/src/ravendata/RavenParameters.java
new file mode 100644
index 00000000..d5d4718f
--- /dev/null
+++ b/src/ravendata/RavenParameters.java
@@ -0,0 +1,10 @@
+package ravendata;
+
+import java.io.Serializable;
+
+public class RavenParameters implements Serializable, Cloneable {
+
+ public static final long serialVersionUID = 1L;
+
+ public String importFile;
+}
diff --git a/src/ravendata/RavenProcess.java b/src/ravendata/RavenProcess.java
new file mode 100644
index 00000000..25993477
--- /dev/null
+++ b/src/ravendata/RavenProcess.java
@@ -0,0 +1,130 @@
+package ravendata;
+
+import java.awt.Color;
+import java.util.ArrayList;
+
+import Acquisition.AcquisitionControl;
+import PamController.InputStoreInfo;
+import PamController.PamController;
+import PamView.PamSymbolType;
+import PamView.dialog.warn.WarnOnce;
+import PamView.symbol.StandardSymbolManager;
+import PamView.symbol.SymbolData;
+import PamguardMVC.PamProcess;
+import dataMap.OfflineDataMap;
+import generalDatabase.DBControlUnit;
+import ravendata.swing.RavenGraphics;
+
+public class RavenProcess extends PamProcess {
+
+ private RavenControl ravenControl;
+
+ private RavenDataBlock ravenDataBlock;
+
+ private RavenLogging ravenLogging;
+
+ private static SymbolData standardSymbol = new SymbolData(PamSymbolType.SYMBOL_SQUARE, 20, 20, false, Color.white, Color.red);
+
+ public RavenProcess(RavenControl pamControlledUnit) {
+ super(pamControlledUnit, null);
+ this.ravenControl = pamControlledUnit;
+ ravenDataBlock = new RavenDataBlock(this, 0);
+ addOutputDataBlock(ravenDataBlock);
+ ravenLogging = new RavenLogging(pamControlledUnit, ravenDataBlock);
+ ravenDataBlock.SetLogging(ravenLogging);
+ ravenDataBlock.setOverlayDraw(new RavenGraphics(ravenDataBlock));
+ ravenDataBlock.setPamSymbolManager(new StandardSymbolManager(ravenDataBlock, standardSymbol));
+ }
+
+ @Override
+ public void pamStart() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void pamStop() {
+ // TODO Auto-generated method stub
+
+ }
+ protected void createPAMGuardData(RavenFileReader fileReader, ArrayList ravenData) {
+ /**
+ * Need to find the acquisition module and then get detailed times of every file, not just
+ * the datamap, which is currently just a normal databsae map of the db entries, so it not
+ * necessarily precise on the starts / ends of files for the viewer.
+ */
+ AcquisitionControl daqControl = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
+ if (daqControl == null) {
+ WarnOnce.showWarning("No acquisition module", "Can only import ROCCA data if there is a Sound Acquisition Module",
+ WarnOnce.WARNING_MESSAGE);
+ return;
+ }
+ // need to get the detailed data map.
+ InputStoreInfo daqInfo = daqControl.getStoreInfo(true);
+ if (daqInfo == null || daqInfo.getAllFileEnds() == null || daqInfo.getAllFileEnds().length == 0) {
+ WarnOnce.showWarning("No sound file info module", "Can only import ROCCA data if sound files arre present to extract absolute times",
+ WarnOnce.WARNING_MESSAGE);
+ return;
+ }
+ // need these to look for gaps to convert ROCCA time to abs time.
+ long[] fileStarts = daqInfo.getFileStartTimes();
+ long[] fileEnds = daqInfo.getAllFileEnds();
+ // make an array of absolute times to match to ROCCA data.
+ // these are the end times of each file (start of first file is known to be 0).
+ long[] absTime = new long[fileStarts.length+1]; // one longer to capture end of last file.
+ for (int i = 0; i < fileStarts.length; i++) {
+ absTime[i+1] = absTime[i] + fileEnds[i]-fileStarts[i];
+ }
+
+ // delete all existing data from database.
+ ravenDataBlock.clearAll();
+ ravenLogging.deleteData(0, System.currentTimeMillis()*2);
+
+ for (RavenDataRow ravenRow : ravenData) {
+ int fileInd = getTimeIndex(ravenRow.getBeginT()*1000, absTime);
+ if (fileInd == absTime.length) {
+ String msg = String.format("Data at time %6.4f is beyond the end of available sound file data", ravenRow.getBeginT());
+ WarnOnce.showWarning("Error importing RAVEN data", msg, WarnOnce.WARNING_MESSAGE);
+ break;
+ }
+ long fileStart = fileStarts[fileInd];
+ long absStart = fileStart + (long) (ravenRow.getBeginT()*1000.)-absTime[fileInd];
+ long duration = (long) ((ravenRow.getEndT()-ravenRow.getBeginT())*1000.);
+ int chanMap = 1<<(ravenRow.getChannel()-1);
+ RavenDataUnit rdu = new RavenDataUnit(absStart, chanMap, duration, ravenRow.getF1(), ravenRow.getF2());
+ getRavenDataBlock().addPamData(rdu);
+ ravenLogging.logData(DBControlUnit.findConnection(), rdu);
+ }
+
+ OfflineDataMap dataMap = ravenDataBlock.getPrimaryDataMap();
+// dataMap.c
+ DBControlUnit dbControl = DBControlUnit.findDatabaseControl();
+ if (dbControl != null) {
+ dbControl.createOfflineDataMap(ravenControl.getGuiFrame(), ravenControl);
+ }
+
+ dataMap = ravenDataBlock.getPrimaryDataMap();
+ }
+
+ /**
+ * Find which file time bin the raven data are in
+ * @param ravenTime
+ * @param absTimes
+ * @return
+ */
+ private int getTimeIndex(double ravenTime, long[] absTimes) {
+ int i = 0;
+ while (i < absTimes.length-1 && ravenTime > absTimes[i+1]) {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * @return the ravenDataBlock
+ */
+ public RavenDataBlock getRavenDataBlock() {
+ return ravenDataBlock;
+ }
+
+}
diff --git a/src/ravendata/swing/RavenGraphics.java b/src/ravendata/swing/RavenGraphics.java
new file mode 100644
index 00000000..db69ce36
--- /dev/null
+++ b/src/ravendata/swing/RavenGraphics.java
@@ -0,0 +1,18 @@
+package ravendata.swing;
+
+import java.awt.Color;
+
+import PamView.PamDetectionOverlayGraphics;
+import PamView.PamSymbol;
+import PamView.PamSymbolType;
+import PamguardMVC.PamDataBlock;
+
+public class RavenGraphics extends PamDetectionOverlayGraphics {
+
+ public static final PamSymbol defaultSymbol = new PamSymbol(PamSymbolType.SYMBOL_SQUARE,12, 12, false, Color.white, Color.red);
+
+ public RavenGraphics(PamDataBlock parentDataBlock) {
+ super(parentDataBlock, defaultSymbol);
+ }
+
+}
diff --git a/src/ravendata/swing/RavenImportDialog.java b/src/ravendata/swing/RavenImportDialog.java
new file mode 100644
index 00000000..af82e452
--- /dev/null
+++ b/src/ravendata/swing/RavenImportDialog.java
@@ -0,0 +1,111 @@
+package ravendata.swing;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import PamUtils.PamFileChooser;
+import PamUtils.PamFileFilter;
+import PamView.dialog.PamDialog;
+import PamView.dialog.PamGridBagContraints;
+import PamView.panel.PamAlignmentPanel;
+import ravendata.RavenParameters;
+
+public class RavenImportDialog extends PamDialog {
+
+ private static RavenImportDialog singleInstance;
+ private RavenParameters ravenParameters;
+
+ private JTextField ravenFile;
+
+ private JButton chooseButton;
+
+
+
+ private RavenImportDialog(Window parentFrame) {
+ super(parentFrame, "Import Raven Data", false);
+ JPanel mainPanel = new JPanel(new GridBagLayout());
+ mainPanel.setBorder(new TitledBorder("Choose Raven selection table"));
+ GridBagConstraints c = new PamGridBagContraints();
+ ravenFile = new JTextField(80);
+ ravenFile.setEditable(false);
+ chooseButton = new JButton("Select ...");
+ c.gridwidth = 2;
+ mainPanel.add(ravenFile, c);
+ c.gridy++;
+ mainPanel.add(new PamAlignmentPanel(chooseButton, BorderLayout.EAST), c);
+
+ chooseButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ chooseFile(e);
+ }
+ });
+ setDialogComponent(mainPanel);
+ }
+
+ protected void chooseFile(ActionEvent e) {
+ PamFileFilter fileFilter = new PamFileFilter("Raven files", ".txt");
+// fileFilter.
+ PamFileChooser chooser = new PamFileChooser(ravenParameters.importFile);
+ chooser.setFileFilter(fileFilter);
+ int ans = chooser.showDialog(this, "Select ...");
+ if (ans == JFileChooser.APPROVE_OPTION) {
+ File f = chooser.getSelectedFile();
+ if (f != null) {
+ ravenFile.setText(f.getAbsolutePath());
+ }
+ }
+ }
+
+ public static RavenParameters showDialog(Window parentFrame, RavenParameters ravenParameters) {
+// if (singleInstance == null) {
+ singleInstance = new RavenImportDialog(parentFrame);
+// }
+ singleInstance.setParams(ravenParameters);
+ singleInstance.setVisible(true);
+ return singleInstance.ravenParameters;
+ }
+
+ private void setParams(RavenParameters ravenParameters) {
+ this.ravenParameters = ravenParameters;
+ ravenFile.setText(ravenParameters.importFile);
+ }
+
+ @Override
+ public boolean getParams() {
+ String fn = ravenFile.getText();
+ if (fn == null) {
+ return showWarning("Error - No file selected");
+ }
+ File f = new File(fn);
+ if (f.exists() == false) {
+ String str = String.format("The file %s does not exist", fn);
+ return showWarning(str);
+ }
+ ravenParameters.importFile = fn;
+ return true;
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ this.ravenParameters = null;
+ }
+
+ @Override
+ public void restoreDefaultSettings() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/targetMotionOld/TargetMotionLocaliser.java b/src/targetMotionOld/TargetMotionLocaliser.java
index dc0c6321..d1922ed7 100644
--- a/src/targetMotionOld/TargetMotionLocaliser.java
+++ b/src/targetMotionOld/TargetMotionLocaliser.java
@@ -3,6 +3,7 @@ package targetMotionOld;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -17,12 +18,17 @@ import javax.swing.SwingWorker;
import pamScrollSystem.AbstractScrollManager;
import pamScrollSystem.ViewerScrollerManager;
+import targetMotionModule.TargetMotionLocaliserProvider;
import targetMotionOld.algorithms.LeastSquaresNew;
import targetMotionOld.algorithms.Simplex2DNew;
import targetMotionOld.algorithms.Simplex3DNew;
import targetMotionOld.dialog.TargetMotionDialog;
+import targetMotionOld.tethys.TMALocalizationCreator;
+import tethys.localization.LocalizationCreator;
import GPS.GPSDataBlock;
import GPS.GpsDataUnit;
+import Localiser.LocalisationAlgorithm;
+import Localiser.LocalisationAlgorithmInfo;
import Localiser.algorithms.timeDelayLocalisers.bearingLoc.AbstractLocaliser;
import Localiser.detectionGroupLocaliser.DetectionGroupOptions;
import Localiser.detectionGroupLocaliser.GroupDetection;
@@ -32,12 +38,14 @@ import PamController.PamControlledUnit;
import PamController.PamController;
import PamController.PamControllerInterface;
import PamDetection.AbstractLocalisation;
+import PamDetection.LocContents;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import PamguardMVC.PamObservable;
import PamguardMVC.PamObserver;
import PamguardMVC.PamObserverAdapter;
import PamguardMVC.debug.Debug;
+import bearinglocaliser.BearingLocaliserParams;
/**
* Reinstated Target motion add-in as used by the click detector. Hope one day still to replace this
@@ -46,7 +54,7 @@ import PamguardMVC.debug.Debug;
*
* @param
*/
-public class TargetMotionLocaliser extends AbstractLocaliser {
+public class TargetMotionLocaliser extends AbstractLocaliser implements LocalisationAlgorithm, LocalisationAlgorithmInfo {
public enum Interractive {START, SAVE, BACK, CANCEL, SETNULL, KEEPOLD};
// public enum WorkStatus {IDLE, LOADING, WAITING};
@@ -77,6 +85,7 @@ public class TargetMotionLocaliser extends AbstractLoc
public int currentEventIndex;
// private T currentEvent;
//private WorkStatus workStatus;
+ private TMALocalizationCreator tmaLocalizationCreator;
public TargetMotionLocaliser(PamControlledUnit pamControlledUnit, PamDataBlock dataBlock, PamDataBlock subDetectionBlock) {
super(dataBlock);
@@ -97,6 +106,11 @@ public class TargetMotionLocaliser extends AbstractLoc
return "Target Motion Localiser";
}
+ @Override
+ public LocalisationAlgorithmInfo getAlgorithmInfo() {
+ return this;
+ }
+
@Override
public boolean localiseDataUnit(T dataUnit) {
// TODO Auto-generated method stub
@@ -719,4 +733,30 @@ public class TargetMotionLocaliser extends AbstractLoc
return null;
}
}
+
+ @Override
+ public int getLocalisationContents() {
+ return LocContents.HAS_LATLONG | LocContents.HAS_AMBIGUITY | LocContents.HAS_DEPTH;
+ }
+
+ @Override
+ public String getAlgorithmName() {
+ return "Target Motion Localiser";
+ }
+
+ @Override
+ public LocalizationCreator getTethysCreator() {
+ if (tmaLocalizationCreator == null) {
+ tmaLocalizationCreator = new TMALocalizationCreator(this);
+ }
+ return tmaLocalizationCreator;
+ }
+
+
+ @Override
+ public Serializable getParameters() {
+ // TODO Auto-generated method stub
+// return new BearingLocaliserParams();
+ return null;
+ }
}
diff --git a/src/targetMotionOld/algorithms/LeastSquaresNew.java b/src/targetMotionOld/algorithms/LeastSquaresNew.java
index 8cf4a869..deeba931 100644
--- a/src/targetMotionOld/algorithms/LeastSquaresNew.java
+++ b/src/targetMotionOld/algorithms/LeastSquaresNew.java
@@ -73,8 +73,7 @@ public class LeastSquaresNew extends AbstractTargetMot
@Override
public LocContents getLocContents() {
- // TODO Auto-generated method stub
- return null;
+ return new LocContents(LocContents.HAS_LATLONG | LocContents.HAS_PERPENDICULARERRORS);
}
@Override
diff --git a/src/targetMotionOld/algorithms/Simplex2DNew.java b/src/targetMotionOld/algorithms/Simplex2DNew.java
index 8b7e5298..fc63ba6c 100644
--- a/src/targetMotionOld/algorithms/Simplex2DNew.java
+++ b/src/targetMotionOld/algorithms/Simplex2DNew.java
@@ -61,8 +61,7 @@ public class Simplex2DNew extends AbstractTargetMotion
@Override
public LocContents getLocContents() {
- // TODO Auto-generated method stub
- return null;
+ return new LocContents(LocContents.HAS_LATLONG | LocContents.HAS_PERPENDICULARERRORS);
}
@Override
diff --git a/src/targetMotionOld/algorithms/Simplex3DNew.java b/src/targetMotionOld/algorithms/Simplex3DNew.java
index f73dfee3..dafe4de8 100644
--- a/src/targetMotionOld/algorithms/Simplex3DNew.java
+++ b/src/targetMotionOld/algorithms/Simplex3DNew.java
@@ -35,8 +35,7 @@ public class Simplex3DNew extends Simplex2DNew{
@Override
public LocContents getLocContents() {
- // TODO Auto-generated method stub
- return null;
+ return new LocContents(LocContents.HAS_LATLONG | LocContents.HAS_DEPTH | LocContents.HAS_DEPTHERROR | LocContents.HAS_PERPENDICULARERRORS);
}
}
diff --git a/src/targetMotionOld/tethys/TMALocalizationCreator.java b/src/targetMotionOld/tethys/TMALocalizationCreator.java
new file mode 100644
index 00000000..6c8d1d63
--- /dev/null
+++ b/src/targetMotionOld/tethys/TMALocalizationCreator.java
@@ -0,0 +1,181 @@
+package targetMotionOld.tethys;
+
+import java.util.List;
+
+import Localiser.LocaliserModel;
+import Localiser.algorithms.locErrors.EllipticalError;
+import Localiser.algorithms.locErrors.LocaliserError;
+import Localiser.detectionGroupLocaliser.GroupLocResult;
+import Localiser.detectionGroupLocaliser.GroupLocalisation;
+import PamDetection.AbstractLocalisation;
+import PamDetection.LocContents;
+import PamUtils.LatLong;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import nilus.AngularCoordinateType;
+import nilus.LocalizationType;
+import nilus.Localize;
+import nilus.WGS84CoordinateType;
+import nilus.LocalizationType.Angular;
+import nilus.LocalizationType.Parameters;
+import nilus.LocalizationType.WGS84;
+import nilus.LocalizationType.Parameters.TargetMotionAnalysis;
+import nilus.Localize.Effort;
+import nilus.Localize.Effort.CoordinateReferenceSystem;
+import pamMaths.PamVector;
+import targetMotionOld.TargetMotionLocaliser;
+import tethys.TethysTimeFuncs;
+import tethys.localization.CoordinateName;
+import tethys.localization.LocalizationBuilder;
+import tethys.localization.LocalizationCreator;
+import tethys.localization.LocalizationSubTypes;
+import tethys.localization.LocalizationTypes;
+import tethys.localization.ReferenceFrame;
+import tethys.localization.TimeReference;
+import tethys.pamdata.AutoTethysProvider;
+
+public class TMALocalizationCreator implements LocalizationCreator {
+
+
+ int maxDimension = 2;
+
+ public TMALocalizationCreator(TargetMotionLocaliser targetMotionLocaliser) {
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public boolean sortLocalisationCoordinates(LocalizationBuilder localizationBuilder, PamDataBlock dataBlock) {
+ Localize doc = localizationBuilder.getCurrentDocument();
+ Effort locEffort = doc.getEffort();
+ locEffort.setTimeReference(TimeReference.beam.toString());
+
+ List locTypes = locEffort.getLocalizationType();
+ locTypes.add(LocalizationTypes.Point.toString());
+ locTypes.add(LocalizationTypes.PerpendicularRange.toString());
+
+ CoordinateReferenceSystem coordRefs = locEffort.getCoordinateReferenceSystem();
+ coordRefs.setName(CoordinateName.WGS84.toString());
+ coordRefs.setSubtype(LocalizationSubTypes.Geographic.toString());
+
+ locEffort.setDimension(2);
+
+ return true;
+ }
+
+ @Override
+ public LocalizationType createLocalization(LocalizationBuilder localizationBuilder, PamDataUnit dataUnit) {
+ /*
+ * Add two types of localisation. A WGS84 and a perpendicular range.
+ */
+ AbstractLocalisation pamLoc = dataUnit.getLocalisation();
+ LatLong latLong = pamLoc.getLatLong(0);
+ if (pamLoc instanceof GroupLocalisation == false || latLong == null) {
+ return localizationBuilder.createStandardLocalization(dataUnit);
+ }
+ LocalizationType loc = localizationBuilder.makeBaseLoc(dataUnit);
+ GroupLocalisation groupLoc = (GroupLocalisation) pamLoc;
+ GroupLocResult groupLocResult = groupLoc.getGroupLocaResult(0);
+ LocaliserModel tmaModel = groupLocResult.getModel();
+ boolean hasDepth = false;
+ LocContents locCont = new LocContents(LocContents.HAS_LATLONG);
+ if (tmaModel != null) {
+ locCont = tmaModel.getLocContents();
+ if (locCont.hasLocContent(LocContents.HAS_DEPTH)) {
+ hasDepth = true;
+ }
+ }
+ int nDim = hasDepth ? 3 : 2;
+ maxDimension = Math.max(maxDimension, nDim);
+ /**
+ * Export the latlong data.
+ */
+ WGS84 wgs84 = new WGS84();
+ WGS84CoordinateType coord = new WGS84CoordinateType();
+ wgs84.setCoordinate(coord);
+ coord.setLongitude(latLong.getLongitude());
+ coord.setLatitude(latLong.getLatitude());
+ if (hasDepth) {
+ coord.setElevationM(AutoTethysProvider.roundDecimalPlaces(latLong.getHeight(),3));
+ }
+ PamVector errors = groupLocResult.getErrorVector();
+ LocaliserError genError = groupLocResult.getLocError();
+ WGS84CoordinateType wgsErr = null;
+ double[] errorVec = null;
+ if (errors != null) {
+ errorVec = errors.getVector();
+ }
+ else if (genError instanceof EllipticalError) {
+ EllipticalError elliptical = (EllipticalError) genError;
+ PamVector dir = genError.getErrorDirection();
+ // these are errors perpendicular and parallel to the track
+ // so aren't really lat long errors.
+ errorVec = elliptical.getEllipseDim();
+ }
+ /*
+ * Needs a bit of work to get errors in correct direction (needs import
+ * of track data for this value ?) and conversion to latlong units.
+ */
+// if (errorVec != null && errorVec.length >= 2) {
+// wgsErr = new WGS84CoordinateType();
+// wgsErr.setLongitude(errorVec[0]);
+// wgsErr.setLatitude(errorVec[1]);
+// if (hasDepth && errorVec.length >= 3) {
+// wgsErr.setElevationM(errorVec[2]);
+// }
+// wgs84.setCoordinateError(wgsErr);
+// }
+
+
+ loc.setWGS84(wgs84);
+
+ // set the TMA information
+ Parameters params = loc.getParameters();
+ if (params == null) {
+ params = new Parameters();
+ loc.setParameters(params);
+ }
+ TargetMotionAnalysis tma = new TargetMotionAnalysis();
+ tma.setStart(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getTimeMilliseconds()));
+ tma.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getEndTimeInMilliseconds()));
+ params.setTargetMotionAnalysis(tma);
+ Long timeAbeam = groupLocResult.getBeamTime();
+ if (timeAbeam != null) {
+ loc.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(timeAbeam));
+ }
+
+// now also output a perpendicular distance.
+ Double perp = groupLocResult.getPerpendicularDistance();
+ if (perp != null) {
+ loc.setPerpendicularRangeM(perp);
+ }
+
+
+ // con only output one type.
+// if (perp != null) {
+// AngularCoordinateType acType = new AngularCoordinateType();
+// acType.setAngle1(90);
+// acType.setDistanceM(AutoTethysProvider.roundDecimalPlaces(perp,1));
+// Angular angular = new Angular();
+// angular.setCoordinate(acType);
+// if (errors != null) {
+// AngularCoordinateType angErr = new AngularCoordinateType();
+// angErr.setDistanceM(errors.norm());
+// angular.setCoordinateError(angErr);
+// }
+// loc.setAngular(angular);
+// }
+
+
+
+ return loc;
+ }
+
+ @Override
+ public boolean checkDocument(LocalizationBuilder localizationBuilder) {
+ boolean ok = localizationBuilder.checkDocument();
+ Effort locEffort = localizationBuilder.getCurrentDocument().getEffort();
+ locEffort.setDimension(maxDimension);
+ return ok;
+ }
+
+}
diff --git a/src/tethys/CollectionHandler.java b/src/tethys/CollectionHandler.java
index 66208fa0..c3eb0bc0 100644
--- a/src/tethys/CollectionHandler.java
+++ b/src/tethys/CollectionHandler.java
@@ -1,5 +1,19 @@
package tethys;
+import java.util.List;
+
+import PamController.PamControlledUnit;
+import PamController.PamguardVersionInfo;
+import PamModel.PamPluginInterface;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamProcess;
+import nilus.Deployment;
+import nilus.DetectionEffort;
+import nilus.DetectionEffortKind;
+import tethys.niluswraps.PDeployment;
+import tethys.output.StreamExportParams;
+import tethys.pamdata.TethysDataProvider;
+
abstract public class CollectionHandler {
private Collection collection;
@@ -35,4 +49,93 @@ abstract public class CollectionHandler {
public abstract String getHelpPoint();
+ /**
+ * Get the Detection Effort part of a Detections document
+ * @param pDeployment
+ * @param dataBlock
+ * @param exportParams
+ * @return
+ */
+ public DetectionEffort getDetectorEffort(PDeployment pDeployment, PamDataBlock dataBlock, StreamExportParams exportParams) {
+ DetectionEffort effort = new DetectionEffort();
+ Deployment deployment = pDeployment.nilusObject;
+ Long effortStart = pDeployment.getAudioStart();
+ Long effortEnd = pDeployment.getAudioEnd();
+ effort.setStart(TethysTimeFuncs.xmlGregCalFromMillis(effortStart));
+ effort.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(effortEnd));
+ // effort.set // no setter for DetectionEffortKind
+ List effortKinds = effort.getKind();
+
+ TethysDataProvider dataProvider = dataBlock.getTethysDataProvider(tethysControl);
+ dataProvider.getEffortKinds(pDeployment, effortKinds, exportParams);
+
+
+ return effort;
+ }
+
+ /**
+ * Method string for Detections Algorithm documents.
+ * @param dataBlock
+ * @return
+ */
+ public String getMethodString(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return null;
+ }
+ PamProcess process = dataBlock.getParentProcess();
+ return "PAMGuard " + process.getProcessName();
+
+ }
+
+ /**
+ * Software string for Detections Algorithm documents.
+ * @param dataBlock
+ * @return
+ */
+ public String getSoftwareString(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return null;
+ }
+ return dataBlock.getLongDataName();
+ }
+
+ /**
+ * Software string for Detections Algorithm documents.
+ * @param dataBlock
+ * @return
+ */
+ public String getVersionString(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return null;
+ }
+ PamProcess process = dataBlock.getParentProcess();
+ PamControlledUnit pcu = process.getPamControlledUnit();
+ PamPluginInterface plugin = pcu.getPlugin();
+ if (plugin == null) {
+ return PamguardVersionInfo.version;
+ }
+ else {
+ return plugin.getVersion();
+ }
+ }
+
+ /**
+ *
+ * @param dataBlock
+ * @return default value is PAMGuard
+ */
+ public String getSupportSoftware(PamDataBlock dataBlock) {
+ return "PAMGuard";
+ }
+
+ /**
+ *
+ * @param dataBlock
+ * @return PAMGuard version
+ */
+ public String getSupportSoftwareVersion(PamDataBlock dataBlock) {
+ // should try to dig into the binary store and get the version from there.
+ return PamguardVersionInfo.version;
+ }
+
}
diff --git a/src/tethys/dbxml/DBXMLQueries.java b/src/tethys/dbxml/DBXMLQueries.java
index b3392568..ee49664b 100644
--- a/src/tethys/dbxml/DBXMLQueries.java
+++ b/src/tethys/dbxml/DBXMLQueries.java
@@ -622,13 +622,15 @@ public class DBXMLQueries {
/**
- * Get the names of all detection documents for a given deployment for all data streams.
- * @param deploymentId
+ * Get the names of all the detection or localisation documents for a given deployment id.
+ * @param collection Localizations or Detetections
+ * @param deploymentId Deployment document id.
* @return
*/
- public ArrayList getDetectionsDocuments(String deploymentId) {
- String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ public ArrayList getDeploymentDocuments(Collection collection, String deploymentId) {
+ String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"collectionname/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"collectionname/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryStr = queryBase.replace("SomeDeploymentId", deploymentId);
+ queryStr = queryStr.replace("collectionname", collection.documentName());
DBQueryResult queryResult = null;
try {
queryResult = executeQuery(queryStr);
@@ -660,6 +662,86 @@ public class DBXMLQueries {
return detectionDocs;
}
+ /**
+ * Get the names of all detection documents for a given deployment for all data streams.
+ * @param deploymentId
+ * @return
+ */
+ public ArrayList getDetectionsDocuments(String deploymentId) {
+ return getDeploymentDocuments(Collection.Detections, deploymentId);
+// String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
+// String queryStr = queryBase.replace("SomeDeploymentId", deploymentId);
+// DBQueryResult queryResult = null;
+// try {
+// queryResult = executeQuery(queryStr);
+// } catch (TethysQueryException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+// if (queryResult == null || queryResult.queryException != null) {
+// return null;
+// }
+//
+// // PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+//
+// Document doc = convertStringToXMLDocument(queryResult.queryResult);
+// if (doc == null) {
+// return null;
+// }
+//
+// ArrayList detectionDocs = new ArrayList<>();
+//
+// NodeList returns = doc.getElementsByTagName("Record");
+// if (returns.getLength() == 0) {
+// returns = doc.getElementsByTagName("Record");
+// }
+// for (int i = 0; i < returns.getLength(); i++) {
+// Node aNode = returns.item(i);
+// detectionDocs.add(aNode.getTextContent());
+// }
+// return detectionDocs;
+ }
+
+ /**
+ * Get the names of all localisation documents for a given deployment for all data streams.
+ * @param deploymentId
+ * @return
+ */
+ public ArrayList getLocalizationsDocuments(String deploymentId) {
+ return getDeploymentDocuments(Collection.Localizations, deploymentId);
+// String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Localize/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Localize/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
+// String queryStr = queryBase.replace("SomeDeploymentId", deploymentId);
+// DBQueryResult queryResult = null;
+// try {
+// queryResult = executeQuery(queryStr);
+// } catch (TethysQueryException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+// if (queryResult == null || queryResult.queryException != null) {
+// return null;
+// }
+//
+// // PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+//
+// Document doc = convertStringToXMLDocument(queryResult.queryResult);
+// if (doc == null) {
+// return null;
+// }
+//
+// ArrayList detectionDocs = new ArrayList<>();
+//
+// NodeList returns = doc.getElementsByTagName("Record");
+// if (returns.getLength() == 0) {
+// returns = doc.getElementsByTagName("Record");
+// }
+// for (int i = 0; i < returns.getLength(); i++) {
+// Node aNode = returns.item(i);
+// detectionDocs.add(aNode.getTextContent());
+// }
+// return detectionDocs;
+ }
+
public int countData(PamDataBlock dataBlock, String deploymentId) {
// /**
// * first query for Detections documents associated with this deployment and datablock.
diff --git a/src/tethys/deployment/DeploymentHandler.java b/src/tethys/deployment/DeploymentHandler.java
index 51768b8f..29345107 100644
--- a/src/tethys/deployment/DeploymentHandler.java
+++ b/src/tethys/deployment/DeploymentHandler.java
@@ -60,7 +60,8 @@ import nilus.Deployment.Data;
import nilus.Deployment.Data.Tracks;
import nilus.Deployment.Data.Tracks.Track;
import nilus.Deployment.Data.Tracks.Track.Point;
-import nilus.Deployment.Data.Tracks.Track.Point.BearingDegN;
+import nilus.Deployment.Data.Tracks.Track.Point.CourseOverGroundDegN;
+import nilus.Deployment.Data.Tracks.Track.Point.HeadingDegN;
import nilus.Deployment.Instrument;
import nilus.Deployment.SamplingDetails;
import nilus.Deployment.Sensors;
@@ -890,6 +891,7 @@ public class DeploymentHandler extends CollectionHandler implements TethysStateO
tracks = new Tracks();
deployment.getData().setTracks(tracks);
}
+ tracks.setSpeedUnit("kn");
List