75101e3d57164f4356a97366fbfd3ae285eec155
[fw/altos] / altosui / AltosConfigFreqUI.java
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import java.util.*;
24 import org.altusmetrum.AltosLib.*;
25 import org.altusmetrum.altosuilib.*;
26
27 class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
28         Frame           frame;
29         JTextField      frequency;
30         JTextField      description;
31         JButton         ok_button, cancel_button;
32         boolean         got_ok;
33
34         public void actionPerformed(ActionEvent e) {
35                 String  cmd = e.getActionCommand();
36
37                 if ("ok".equals(cmd)) {
38                         got_ok = true;
39                         setVisible(false);
40                 }
41                 if ("cancel".equals(cmd)) {
42                         got_ok = false;
43                         setVisible(false);
44                 }
45         }
46
47         public AltosFrequency get() {
48                 if (!got_ok)
49                         return null;
50
51                 String  f_s = frequency.getText();
52                 String  d_s = description.getText();
53
54                 try {
55                         double  f_d = Double.parseDouble(f_s);
56
57                         return new AltosFrequency(f_d, d_s);
58                 } catch (NumberFormatException ne) {
59                 }
60                 return null;
61         }
62
63         public AltosEditFreqUI(Frame in_frame, AltosFrequency existing) {
64                 super(in_frame, true);
65
66                 got_ok = false;
67                 frame = in_frame;
68
69                 Container pane = getContentPane();
70                 pane.setLayout(new GridBagLayout());
71
72                 GridBagConstraints c = new GridBagConstraints();
73                 c.insets = new Insets (4,4,4,4);
74                 
75                 c.fill = GridBagConstraints.NONE;
76                 c.anchor = GridBagConstraints.WEST;
77                 c.gridx = 0;
78                 c.gridy = 0;
79                 c.gridwidth = 1;
80                 c.gridheight = 1;
81                 c.weightx = 0;
82                 c.weighty = 0;
83                 pane.add(new JLabel("Frequency"), c);
84
85                 frequency = new JTextField(12);
86                 c.fill = GridBagConstraints.NONE;
87                 c.anchor = GridBagConstraints.WEST;
88                 c.gridx = 1;
89                 c.gridy = 0;
90                 c.gridwidth = 1;
91                 c.gridheight = 1;
92                 c.weightx = 0;
93                 c.weighty = 0;
94                 pane.add(frequency, c);
95
96                 c.fill = GridBagConstraints.NONE;
97                 c.anchor = GridBagConstraints.WEST;
98                 c.gridx = 0;
99                 c.gridy = 1;
100                 c.gridwidth = 1;
101                 c.gridheight = 1;
102                 c.weightx = 0;
103                 c.weighty = 0;
104                 pane.add(new JLabel("Description"), c);
105
106                 description = new JTextField(12);
107                 c.fill = GridBagConstraints.NONE;
108                 c.anchor = GridBagConstraints.WEST;
109                 c.gridx = 1;
110                 c.gridy = 1;
111                 c.gridwidth = 1;
112                 c.gridheight = 1;
113                 c.weightx = 0;
114                 c.weighty = 0;
115                 pane.add(description, c);
116
117                 ok_button = new JButton("OK");
118                 ok_button.setActionCommand("ok");
119                 ok_button.addActionListener(this);
120                 c.fill = GridBagConstraints.NONE;
121                 c.anchor = GridBagConstraints.WEST;
122                 c.gridx = 0;
123                 c.gridy = 2;
124                 c.gridwidth = 1;
125                 c.gridheight = 1;
126                 c.weightx = 0;
127                 c.weighty = 0;
128                 pane.add(ok_button, c);
129                 
130                 cancel_button = new JButton("Cancel");
131                 cancel_button.setActionCommand("cancel");
132                 cancel_button.addActionListener(this);
133                 c.fill = GridBagConstraints.NONE;
134                 c.anchor = GridBagConstraints.WEST;
135                 c.gridx = 1;
136                 c.gridy = 2;
137                 c.gridwidth = 1;
138                 c.gridheight = 1;
139                 c.weightx = 0;
140                 c.weighty = 0;
141                 pane.add(cancel_button, c);
142                 
143                 if (existing == null)
144                         setTitle("Add New Frequency");
145                 else {
146                         setTitle("Edit Existing Frequency");
147                         frequency.setText(String.format("%7.3f", existing.frequency));
148                         description.setText(existing.description);
149                 }
150                 getRootPane().setDefaultButton(ok_button);
151
152                 pack();
153                 setLocationRelativeTo(frame);
154                 
155         }
156
157         public AltosEditFreqUI(Frame in_frame) {
158                 this(in_frame, (AltosFrequency) null);
159         }
160 }
161
162 public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener {
163
164         Frame frame;
165         LinkedList<ActionListener> listeners;
166
167         class FrequencyList extends JList {
168                 DefaultListModel list_model;
169
170                 public void add(AltosFrequency frequency) {
171                         int i;
172                         for (i = 0; i < list_model.size(); i++) {
173                                 AltosFrequency  f = (AltosFrequency) list_model.get(i);
174                                 if (frequency.frequency == f.frequency)
175                                         return;
176                                 if (frequency.frequency < f.frequency)
177                                         break;
178                         }
179                         list_model.insertElementAt(frequency, i);
180                 }
181
182                 public void remove(AltosFrequency frequency) {
183                         list_model.removeElement(frequency);
184                 }
185
186                 //Subclass JList to workaround bug 4832765, which can cause the
187                 //scroll pane to not let the user easily scroll up to the beginning
188                 //of the list.  An alternative would be to set the unitIncrement
189                 //of the JScrollBar to a fixed value. You wouldn't get the nice
190                 //aligned scrolling, but it should work.
191                 public int getScrollableUnitIncrement(Rectangle visibleRect,
192                                                       int orientation,
193                                                       int direction) {
194                         int row;
195                         if (orientation == SwingConstants.VERTICAL &&
196                             direction < 0 && (row = getFirstVisibleIndex()) != -1) {
197                                 Rectangle r = getCellBounds(row, row);
198                                 if ((r.y == visibleRect.y) && (row != 0))  {
199                                         Point loc = r.getLocation();
200                                         loc.y--;
201                                         int prevIndex = locationToIndex(loc);
202                                         Rectangle prevR = getCellBounds(prevIndex, prevIndex);
203
204                                         if (prevR == null || prevR.y >= r.y) {
205                                                 return 0;
206                                         }
207                                         return prevR.height;
208                                 }
209                         }
210                         return super.getScrollableUnitIncrement(
211                                 visibleRect, orientation, direction);
212                 }
213
214                 public AltosFrequency selected() {
215                         AltosFrequency  f = (AltosFrequency) getSelectedValue();
216                         return f;
217                 }
218
219                 public AltosFrequency[] frequencies() {
220                         AltosFrequency[]        ret;
221
222                         ret = new AltosFrequency[list_model.size()];
223                         for (int i = 0; i < list_model.size(); i++)
224                                 ret[i] = (AltosFrequency) list_model.get(i);
225                         return ret;
226                 }
227
228                 public FrequencyList(AltosFrequency[] in_frequencies) {
229                         list_model = new DefaultListModel();
230                         setModel(list_model);
231                         setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
232                         setLayoutOrientation(JList.HORIZONTAL_WRAP);
233                         for (int i = 0; i < in_frequencies.length; i++) {
234                                 add(in_frequencies[i]);
235                         }
236                         setVisibleRowCount(in_frequencies.length);
237                 }
238         }
239
240         FrequencyList   frequencies;
241
242         void save_frequencies() {
243                 AltosUIPreferences.set_common_frequencies(frequencies.frequencies());
244         }
245
246         JButton add, edit, remove;
247
248         JButton cancel, ok;
249
250         public void actionPerformed(ActionEvent e) {
251                 String  cmd = e.getActionCommand();
252
253                 if ("ok".equals(cmd)) {
254                         save_frequencies();
255                         setVisible(false);
256                 } else if ("cancel".equals(cmd)) {
257                         setVisible(false);
258                 } else if ("add".equals(cmd)) {
259                         AltosEditFreqUI ui = new AltosEditFreqUI(frame);
260                         ui.setVisible(true);
261                         AltosFrequency  f = ui.get();
262                         if (f != null)
263                                 frequencies.add(f);
264                 } else if ("edit".equals(cmd)) {
265                         AltosFrequency  old_f = frequencies.selected();
266                         if (old_f == null)
267                                 return;
268                         AltosEditFreqUI ui = new AltosEditFreqUI(frame, old_f);
269                         ui.setVisible(true);
270                         AltosFrequency  new_f = ui.get();
271                         if (new_f != null) {
272                                 if (old_f != null)
273                                         frequencies.remove(old_f);
274                                 frequencies.add(new_f);
275                         }
276                 } else if ("remove".equals(cmd)) {
277                         AltosFrequency  old_f = frequencies.selected();
278                         if (old_f == null)
279                                 return;
280                         int ret = JOptionPane.showConfirmDialog(this,
281                                                                 String.format("Remove frequency \"%s\"?",
282                                                                               old_f.toShortString()),
283                                                                 "Remove Frequency",
284                                                                 JOptionPane.YES_NO_OPTION);
285                         if (ret == JOptionPane.YES_OPTION)
286                                 frequencies.remove(old_f);
287                 }
288         }
289
290         public AltosFrequency[] frequencies() {
291                 return frequencies.frequencies();
292         }
293         
294         public AltosConfigFreqUI(Frame in_frame,
295                                  AltosFrequency[] in_frequencies) {
296                 super(in_frame, "Manage Frequencies", true);
297
298                 frame = in_frame;
299
300                 listeners = new LinkedList<ActionListener>();
301
302                 frequencies = new FrequencyList(in_frequencies);
303
304                 Container pane = getContentPane();
305                 pane.setLayout(new GridBagLayout());
306
307                 GridBagConstraints c = new GridBagConstraints();
308                 c.insets = new Insets(4,4,4,4);
309
310                 /*
311                  * Frequencies label and list
312                  */
313                 c.fill = GridBagConstraints.NONE;
314                 c.anchor = GridBagConstraints.WEST;
315                 c.gridx = 0;
316                 c.gridy = 0;
317                 c.gridwidth = 1;
318                 c.gridheight = 1;
319                 c.weightx = 0;
320                 c.weighty = 0;
321                 pane.add(new JLabel("Frequencies"), c);
322
323                 JScrollPane list_scroller = new JScrollPane(frequencies);
324                 list_scroller.setAlignmentX(LEFT_ALIGNMENT);
325                 c.fill = GridBagConstraints.BOTH;
326                 c.anchor = GridBagConstraints.WEST;
327                 c.gridx = 0;
328                 c.gridy = 1;
329                 c.gridwidth = 6;
330                 c.gridheight = 2;
331                 c.weightx = 1;
332                 c.weighty = 1;
333                 pane.add(list_scroller, c);
334
335                 add = new JButton("Add");
336                 add.setActionCommand("add");
337                 add.addActionListener(this);
338                 c.fill = GridBagConstraints.NONE;
339                 c.anchor = GridBagConstraints.CENTER;
340                 c.gridx = 0;
341                 c.gridy = 3;
342                 c.gridwidth = 2;
343                 c.gridheight = 1;
344                 c.weightx = 0;
345                 c.weighty = 0;
346                 pane.add(add, c);
347
348                 edit = new JButton("Edit");
349                 edit.setActionCommand("edit");
350                 edit.addActionListener(this);
351                 c.fill = GridBagConstraints.NONE;
352                 c.anchor = GridBagConstraints.CENTER;
353                 c.gridx = 2;
354                 c.gridy = 3;
355                 c.gridwidth = 2;
356                 c.gridheight = 1;
357                 c.weightx = 0;
358                 c.weighty = 0;
359                 pane.add(edit, c);
360
361                 remove = new JButton("Remove");
362                 remove.setActionCommand("remove");
363                 remove.addActionListener(this);
364                 c.fill = GridBagConstraints.NONE;
365                 c.anchor = GridBagConstraints.CENTER;
366                 c.gridx = 4;
367                 c.gridy = 3;
368                 c.gridwidth = 2;
369                 c.gridheight = 1;
370                 c.weightx = 0;
371                 c.weighty = 0;
372                 pane.add(remove, c);
373
374                 ok = new JButton("OK");
375                 ok.setActionCommand("ok");
376                 ok.addActionListener(this);
377                 c.fill = GridBagConstraints.NONE;
378                 c.anchor = GridBagConstraints.CENTER;
379                 c.gridx = 0;
380                 c.gridy = 4;
381                 c.gridwidth = 3;
382                 c.gridheight = 1;
383                 c.weightx = 0;
384                 c.weighty = 0;
385                 pane.add(ok, c);
386
387                 cancel = new JButton("Cancel");
388                 cancel.setActionCommand("cancel");
389                 cancel.addActionListener(this);
390                 c.fill = GridBagConstraints.NONE;
391                 c.anchor = GridBagConstraints.CENTER;
392                 c.gridx = 3;
393                 c.gridy = 4;
394                 c.gridwidth = 3;
395                 c.gridheight = 1;
396                 c.weightx = 0;
397                 c.weighty = 0;
398                 pane.add(cancel, c);
399
400                 pack();
401                 setLocationRelativeTo(frame);
402         }
403
404         public static void show(Component frameComp) {
405                 Frame   frame = JOptionPane.getFrameForComponent(frameComp);
406                 AltosConfigFreqUI       dialog;
407
408                 dialog = new AltosConfigFreqUI(frame, AltosUIPreferences.common_frequencies());
409                 dialog.setVisible(true);
410         }
411
412 }