diff --git a/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/GpsFixDialog.java b/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/GpsFixDialog.java new file mode 100644 index 0000000000..fa1bb6dbd1 --- /dev/null +++ b/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/GpsFixDialog.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENCE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: Miguel Carvalho + * 12/Feb/2025 + */ +package pt.lsts.neptus.plugins.sim; + +import net.miginfocom.swing.MigLayout; +import pt.lsts.neptus.gui.LocationCopyPastePanel; +import pt.lsts.neptus.i18n.I18n; +import pt.lsts.neptus.types.coord.LocationType; +import pt.lsts.neptus.util.GuiUtils; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Objects; + +public class GpsFixDialog extends JDialog { + + private SimulationActionsPlugin plugin; + private Dimension prefSize = new Dimension(350, 160); + private JComboBox comboBox = new JComboBox<>(); + private JPanel setLatLonPanel; + private JTextField latTextField = new JTextField(6); + private JTextField lonTextField = new JTextField(6); + + public GpsFixDialog(SimulationActionsPlugin plugin) { + super(); + this.plugin = plugin; + initComponents(); + this.setAlwaysOnTop(true); + } + + private void initComponents() { + setLayout(new MigLayout("fill", "[]", "[]")); + setSize(prefSize); + this.setTitle(I18n.text("GPS Fix")); + + createComboPanel(); + createCoordinatePanel(); + createButtonsPanel(); + GuiUtils.centerOnScreen(this); + } + + private void createComboPanel() { + JPanel comboPanel = new JPanel(new MigLayout("insets 10 10 0 10, fill", "[][]", "[]")); + JLabel comboLabel = new JLabel("GPS Fix to:"); + String[] options = {"Center of Map", "Coordinates"}; + comboBox = new JComboBox<>(options); + comboPanel.add(comboLabel); + comboPanel.add(comboBox); + add(comboPanel, "align center, wrap"); + + comboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (comboBox.getSelectedIndex() == 1) { + setLatLonPanel.setVisible(true); + } + else { + setLatLonPanel.setVisible(false); + } + revalidate(); + repaint(); + } + }); + } + + private void createCoordinatePanel() { + setLatLonPanel = new JPanel(new MigLayout("insets 0 10 5 10, fill", "[][]", "[]")); + JLabel latLabel = new JLabel(I18n.text("Latitude:")); + setLatLonPanel.add(latLabel); + setLatLonPanel.add(latTextField, ""); + JLabel lonLabel = new JLabel(I18n.text("Longitude:")); + setLatLonPanel.add(lonLabel); + setLatLonPanel.add(lonTextField, ""); + LocationCopyPastePanel copyPastePanel = new LocationCopyPastePanel() { + @Override + public void setLocationType(LocationType locationType) { + LocationType loc = locationType.getNewAbsoluteLatLonDepth(); + latTextField.setText(String.valueOf(loc.getLatitudeDegs())); + latTextField.setCaretPosition(0); + lonTextField.setText(String.valueOf(loc.getLongitudeDegs())); + lonTextField.setCaretPosition(0); + } + + @Override + public LocationType getLocationType() { + LocationType lt = null; + try { + double latDeg = Double.parseDouble(latTextField.getText()); + double lonDeg = Double.parseDouble(lonTextField.getText()); + lt = new LocationType(latDeg, lonDeg); + } + catch (Exception exp) { + System.out.println("Unable to convert values to latitude and longitude"); + } + return lt; + } + }; + copyPastePanel.setBorder(null); + setLatLonPanel.add(copyPastePanel); + setLatLonPanel.setVisible(false); + add(setLatLonPanel, "align center, wrap, hidemode 3"); + } + + private void createButtonsPanel() { + JPanel buttonPanel = new JPanel(new MigLayout("insets 0 10 10 10, fill", "[][]", "[]")); + JButton okButton = new JButton("OK"); + JButton cancelButton = new JButton("Cancel"); + buttonPanel.add(okButton, "sizegroup btn, gapright 5"); + buttonPanel.add(cancelButton, "sizegroup btn, gapleft 5"); + add(buttonPanel, "align center"); + + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (comboBox.getSelectedItem().equals("Coordinates")) { + String latText = latTextField.getText(); + String lonText = lonTextField.getText(); + if (Objects.equals(latText, "") || Objects.equals(lonText, "")) { + GuiUtils.errorMessage(GpsFixDialog.this, I18n.text("Error"), + I18n.text("Latitude and longitude cannot be empty when setting a position."), + ModalityType.DOCUMENT_MODAL); + } + LocationType lt = null; + try { + double latDeg = Double.parseDouble(latTextField.getText()); + double lonDeg = Double.parseDouble(lonTextField.getText()); + lt = new LocationType(latDeg, lonDeg); + } + catch (Exception exp) { + System.out.println("Unable to convert values to latitude and longitude"); + } + if (lt != null) { + plugin.sendGpsFix(lt); + } + } + else { + plugin.sendGpsFixToCenter(); + } + } + }); + + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + dispose(); + } + }); + + GuiUtils.reactEnterKeyPress(okButton); + GuiUtils.reactEscapeKeyPress(cancelButton); + } +} diff --git a/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/SimulationActionsPlugin.java b/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/SimulationActionsPlugin.java index 08341e5412..771df9fc8b 100644 --- a/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/SimulationActionsPlugin.java +++ b/plugins-dev/simulation/src/java/pt/lsts/neptus/plugins/sim/SimulationActionsPlugin.java @@ -35,9 +35,13 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Calendar; +import java.util.Collection; import java.util.GregorianCalendar; import java.util.Vector; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; import javax.swing.JOptionPane; import pt.lsts.imc.GpsFix; @@ -45,7 +49,10 @@ import pt.lsts.neptus.console.ConsolePanel; import pt.lsts.neptus.console.plugins.planning.MapPanel; import pt.lsts.neptus.i18n.I18n; +import pt.lsts.neptus.planeditor.IEditorMenuExtension; +import pt.lsts.neptus.planeditor.IMapPopup; import pt.lsts.neptus.plugins.NeptusProperty; +import pt.lsts.neptus.renderer2d.ILayerPainter; import pt.lsts.neptus.types.coord.LocationType; import pt.lsts.neptus.util.GuiUtils; @@ -53,12 +60,17 @@ * @author zp * */ -public class SimulationActionsPlugin extends ConsolePanel { +public class SimulationActionsPlugin extends ConsolePanel implements IEditorMenuExtension { protected final String menuTools = I18n.text("Tools"); protected final String menuSimulation = I18n.text("Simulation"); protected final String menuSendFix = I18n.text("Send GPS Fix"); protected final String menuChooseHeight = I18n.text("Simulated Height..."); + + private Vector renderersPopups = new Vector(); + private Vector renderers = new Vector(); + + private GpsFixDialog gpsFixDialog; @NeptusProperty private double simulatedHeight = 0; @@ -72,6 +84,7 @@ public SimulationActionsPlugin(ConsoleLayout console) { @Override public void initSubPanel() { + gpsFixDialog = new GpsFixDialog(this); addMenuItem(menuTools+">"+menuSimulation+">"+menuSendFix, null, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -86,6 +99,11 @@ public void actionPerformed(ActionEvent arg0) { selectHeight(); } }); + + renderersPopups = getConsole().getSubPanelsOfInterface(IMapPopup.class); + for (IMapPopup str2d : renderersPopups) { + str2d.addMenuExtension(this); + } } private void selectHeight() { @@ -103,38 +121,48 @@ private void selectHeight() { } private void sendGpsFix() { - Vector pps = getConsole().getSubPanelsOfClass(MapPanel.class); + + Vector pps = getConsole().getSubPanelsOfClass(MapPanel.class); if (pps.isEmpty()) { GuiUtils.errorMessage(I18n.text("Cannot send GPS fix"), I18n.text("There must be a planning panel in the console")); return; } else { - LocationType loc = pps.firstElement().getRenderer().getCenter(); - loc.convertToAbsoluteLatLonDepth(); - Calendar cal = GregorianCalendar.getInstance(); - - GpsFix fix = GpsFix.create( - "validity", 0xFFFF, - "type", "MANUAL_INPUT", - "utc_year", cal.get(Calendar.YEAR), - "utc_month", cal.get(Calendar.MONTH)+1, - "utc_day", cal.get(Calendar.DATE), - "utc_time", cal.get(Calendar.HOUR_OF_DAY) * 3600 + cal.get(Calendar.MINUTE) * 60 + cal.get(Calendar.SECOND), - "lat", loc.getLatitudeRads(), - "lon", loc.getLongitudeRads(), - "height", simulatedHeight, - "satellites", 4, - "cog", 0, - "sog", 0, - "hdop", 1, - "vdop", 1, - "hacc", 2, - "vacc", 2 - ); - send(fix); + GuiUtils.centerParent(gpsFixDialog, getConsole()); + gpsFixDialog.setVisible(true); } } + public void sendGpsFixToCenter() { + Vector pps = getConsole().getSubPanelsOfClass(MapPanel.class); + LocationType loc = pps.firstElement().getRenderer().getCenter(); + sendGpsFix(loc); + } + + public void sendGpsFix(LocationType loc) { + loc.convertToAbsoluteLatLonDepth(); + Calendar cal = GregorianCalendar.getInstance(); + GpsFix fix = GpsFix.create( + "validity", 0xFFFF, + "type", "MANUAL_INPUT", + "utc_year", cal.get(Calendar.YEAR), + "utc_month", cal.get(Calendar.MONTH)+1, + "utc_day", cal.get(Calendar.DATE), + "utc_time", cal.get(Calendar.HOUR_OF_DAY) * 3600 + cal.get(Calendar.MINUTE) * 60 + cal.get(Calendar.SECOND), + "lat", loc.getLatitudeRads(), + "lon", loc.getLongitudeRads(), + "height", simulatedHeight, + "satellites", 4, + "cog", 0, + "sog", 0, + "hdop", 1, + "vdop", 1, + "hacc", 2, + "vacc", 2 + ); + send(fix); + } + /* (non-Javadoc) * @see pt.lsts.neptus.plugins.SimpleSubPanel#cleanSubPanel() */ @@ -143,4 +171,37 @@ public void cleanSubPanel() { // TODO Auto-generated method stub } + + /* + * (non-Javadoc) + * + * @see + * pt.lsts.neptus.planeditor.IEditorMenuExtension#getApplicableItems(pt.lsts.neptus.types.coord.LocationType + * , pt.lsts.neptus.planeditor.IMapPopup) + */ + @Override + public Collection getApplicableItems(LocationType loc, IMapPopup source) { + final LocationType l = new LocationType(loc); + Vector menus = new Vector(); + JMenu gpsFixMenu = new JMenu(I18n.text("Send GPS fix to...")); + menus.add(gpsFixMenu); + + AbstractAction sendToCenter = new AbstractAction(I18n.text("Map Center")) { + @Override + public void actionPerformed(ActionEvent e) { + sendGpsFixToCenter(); + } + }; + gpsFixMenu.add(new JMenuItem(sendToCenter)); + + AbstractAction sendToCoord = new AbstractAction(I18n.text("Here")) { + @Override + public void actionPerformed(ActionEvent e) { + sendGpsFix(l); + } + }; + gpsFixMenu.add(new JMenuItem(sendToCoord)); + + return menus; + } }