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