]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/function/PlusCodeFunction.java
Version 20.4, May 2021
[GpsPrune.git] / src / tim / prune / function / PlusCodeFunction.java
1 package tim.prune.function;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.FlowLayout;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.awt.event.KeyAdapter;
9 import java.awt.event.KeyEvent;
10 import java.awt.event.MouseAdapter;
11 import java.awt.event.MouseEvent;
12
13 import javax.swing.BorderFactory;
14 import javax.swing.JButton;
15 import javax.swing.JDialog;
16 import javax.swing.JLabel;
17 import javax.swing.JOptionPane;
18 import javax.swing.JPanel;
19 import javax.swing.JTextField;
20 import javax.swing.SwingConstants;
21
22 import tim.prune.App;
23 import tim.prune.GenericFunction;
24 import tim.prune.I18nManager;
25 import tim.prune.data.Field;
26 import tim.prune.function.olc.OlcArea;
27 import tim.prune.function.olc.OlcDecoder;
28 import tim.prune.gui.GuiGridLayout;
29
30 /**
31  * Class to provide the function to parse
32  * OpenLocationCodes, or PlusCodes
33  */
34 public class PlusCodeFunction extends GenericFunction
35 {
36         private JDialog _dialog = null;
37         private JTextField _codeField = null;
38         private JButton _okButton = null;
39
40
41         /**
42          * Constructor
43          * @param inApp application object for callback
44          */
45         public PlusCodeFunction(App inApp)
46         {
47                 super(inApp);
48         }
49
50         /** Get the name key */
51         public String getNameKey() {
52                 return "function.enterpluscode";
53         }
54
55         /**
56          * Begin the function
57          */
58         public void begin()
59         {
60                 // Make dialog window
61                 if (_dialog == null)
62                 {
63                         _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
64                         _dialog.setLocationRelativeTo(_parentFrame);
65                         _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
66                         _dialog.getContentPane().add(makeDialogComponents());
67                         _dialog.pack();
68                 }
69                 // MAYBE: Paste clipboard into the edit field
70                 _codeField.setText("");
71                 enableOK();
72                 _dialog.setVisible(true);
73         }
74
75
76         /**
77          * Create dialog components
78          * @return Panel containing all gui elements in dialog
79          */
80         private Component makeDialogComponents()
81         {
82                 JPanel dialogPanel = new JPanel();
83                 dialogPanel.setLayout(new BorderLayout(0, 10));
84                 dialogPanel.add(new JLabel(I18nManager.getText("dialog.pluscode.desc")), BorderLayout.NORTH);
85                 JPanel mainPanel = new JPanel();
86                 GuiGridLayout grid = new GuiGridLayout(mainPanel);
87                 _codeField = new JTextField("", 12);
88                 // Listeners to enable/disable ok button
89                 KeyAdapter keyListener = new KeyAdapter() {
90                         /** Key released */
91                         public void keyReleased(KeyEvent inE) {
92                                 enableOK();
93                                 if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
94                                         _dialog.dispose();
95                                 }
96                         }
97                 };
98                 MouseAdapter mouseListener = new MouseAdapter() {
99                         public void mouseReleased(MouseEvent inE) {
100                                 enableOK();
101                         }
102                 };
103                 _codeField.addKeyListener(keyListener);
104                 _codeField.addMouseListener(mouseListener);
105                 JLabel codeLabel = new JLabel(I18nManager.getText("dialog.pluscode.code"));
106                 codeLabel.setHorizontalAlignment(SwingConstants.RIGHT);
107                 grid.add(codeLabel);
108                 grid.add(_codeField);
109                 dialogPanel.add(mainPanel, BorderLayout.CENTER);
110                 // button panel at bottom
111                 JPanel buttonPanel = new JPanel();
112                 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
113                 _okButton = new JButton(I18nManager.getText("button.ok"));
114                 ActionListener okListener = new ActionListener() {
115                         public void actionPerformed(ActionEvent e)
116                         {
117                                 if (_okButton.isEnabled()) {finish();}
118                         }
119                 };
120                 _okButton.addActionListener(okListener);
121                 _okButton.setEnabled(false);
122                 _codeField.addActionListener(okListener);
123                 buttonPanel.add(_okButton);
124                 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
125                 cancelButton.addActionListener(new ActionListener() {
126                         public void actionPerformed(ActionEvent e)
127                         {
128                                 _dialog.dispose();
129                         }
130                 });
131                 buttonPanel.add(cancelButton);
132                 dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
133                 dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
134                 return dialogPanel;
135         }
136
137         /**
138          * Enable or disable the OK button based on the contents of the text field
139          */
140         private void enableOK()
141         {
142                 String text = _codeField.getText();
143                 _okButton.setEnabled(text != null && text.length() > 7
144                         && text.indexOf(' ') < 0 && text.indexOf(',') < 0);
145         }
146
147         /**
148          * Finish the dialog when OK pressed
149          */
150         private void finish()
151         {
152                 OlcArea area = OlcDecoder.decode(_codeField.getText());
153
154                 if (area == null)
155                 {
156                         JOptionPane.showMessageDialog(_parentFrame,
157                                 I18nManager.getText("dialog.pluscode.nothingfound"),
158                                 I18nManager.getText(getNameKey()), JOptionPane.ERROR_MESSAGE);
159                 }
160                 else if (loadTrack(area))
161                 {
162                         _dialog.dispose();
163                 }
164         }
165
166         /**
167          * Load the generated points from the given area
168          * @param inArea rectangular area
169          * @return true on success
170          */
171         private boolean loadTrack(OlcArea inArea)
172         {
173                 if (inArea == null)
174                 {
175                         return false;
176                 }
177
178                 final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.WAYPT_NAME};
179                 _app.autoAppendNextFile();
180
181                 if (inArea.minLat == inArea.maxLat && inArea.minLon == inArea.maxLon)
182                 {
183                         String[][] pointData = new String[1][];
184                         pointData[0] = new String[3]; // lat, long, name
185                         pointData[0][0] = "" + inArea.minLat;
186                         pointData[0][1] = "" + inArea.minLon;
187                         pointData[0][2] = _codeField.getText();
188                         _app.informDataLoaded(fields, pointData, null, null);
189                 }
190                 else
191                 {
192                         String[][] pointData = new String[6][];
193                         for (int i=0; i<5; i++)
194                         {
195                                 pointData[i] = new String[3]; // lat, long, name
196                                 pointData[i][0] = "" + ((i%4==0 || i==3) ? inArea.minLat : inArea.maxLat);
197                                 pointData[i][1] = "" + ((i%4==0 || i==1) ? inArea.minLon : inArea.maxLon);
198                                 pointData[i][2] = null;
199                         }
200                         // Middle point with name
201                         pointData[5] = new String[3]; // lat, long, name
202                         pointData[5][0] = "" + ((inArea.minLat + inArea.maxLat) / 2.0);
203                         pointData[5][1] = "" + ((inArea.minLon + inArea.maxLon) / 2.0);
204                         pointData[5][2] = _codeField.getText();
205                         _app.informDataLoaded(fields, pointData, null, null);
206                 }
207                 return true;
208         }
209 }