001 /*
002 Copyright (C) 2003 Adam Olsen
003
004 This program is free software; you can redistribute it and/or modify
005 it under the terms of the GNU General Public License as published by
006 the Free Software Foundation; either version 1, or (at your option)
007 any later version.
008
009 This program is distributed in the hope that it will be useful,
010 but WITHOUT ANY WARRANTY; without even the implied warranty of
011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 GNU General Public License for more details.
013
014 You should have received a copy of the GNU General Public License
015 along with this program; if not, write to the Free Software
016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
017 */
018
019 package com.valhalla.jbother;
020
021 import java.awt.BorderLayout;
022 import java.awt.Component;
023 import java.awt.Dimension;
024 import java.awt.GridBagConstraints;
025 import java.awt.GridBagLayout;
026 import java.awt.event.ActionEvent;
027 import java.awt.event.ActionListener;
028 import java.text.MessageFormat;
029 import java.util.ArrayList;
030 import java.util.Iterator;
031 import java.util.Locale;
032 import java.util.ResourceBundle;
033 import java.util.Vector;
034
035 import javax.swing.BorderFactory;
036 import javax.swing.Box;
037 import javax.swing.BoxLayout;
038 import javax.swing.JButton;
039 import javax.swing.JCheckBox;
040 import javax.swing.JComboBox;
041 import javax.swing.JComponent;
042 import javax.swing.JDialog;
043 import javax.swing.JFrame;
044 import javax.swing.JLabel;
045 import javax.swing.JList;
046 import javax.swing.JPanel;
047 import javax.swing.JPasswordField;
048 import javax.swing.JScrollPane;
049 import javax.swing.JTextField;
050 import javax.swing.ListCellRenderer;
051
052 import org.jivesoftware.smackx.Form;
053 import org.jivesoftware.smackx.FormField;
054
055 import com.valhalla.gui.MJTextArea;
056 import com.valhalla.gui.MJTextField;
057 import com.valhalla.gui.Standard;
058
059 /**
060 * A visual representation of a DataForm
061 *
062 * @author Adam Olsen
063 */
064 public class JBDataForm extends JDialog {
065 private ResourceBundle resources = ResourceBundle.getBundle(
066 "JBotherBundle", Locale.getDefault());
067
068 private JPanel main;
069
070 private JPanel container = new JPanel();
071
072 private JButton okButton = new JButton(resources.getString("okButton"));
073
074 private JButton cancelButton = new JButton(resources
075 .getString("cancelButton"));
076
077 private Vector fields = new Vector();
078
079 private GridBagLayout layout = new GridBagLayout();
080
081 private GridBagConstraints c = new GridBagConstraints();
082
083 private Vector listeners = new Vector();
084
085 private Form form;
086
087 public JBDataForm(JFrame parent, Form form) {
088 super(parent, form.getTitle());
089 this.form = form;
090 main = (JPanel) getContentPane();
091 main.setLayout(new BorderLayout(5, 5));
092 main.setBorder(BorderFactory.createTitledBorder(form.getTitle()));
093 JLabel instructions = new JLabel("<html>"
094 + form.getInstructions().replaceAll("\\n", "<br>") + "</html>");
095 instructions.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
096 main.add(instructions, BorderLayout.NORTH);
097
098 JPanel buttonPanel = new JPanel();
099 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
100 buttonPanel.add(Box.createHorizontalGlue());
101 buttonPanel.add(okButton);
102 buttonPanel.add(cancelButton);
103 buttonPanel.add(Box.createHorizontalGlue());
104 buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
105 main.add(buttonPanel, BorderLayout.SOUTH);
106
107 JScrollPane scroll = new JScrollPane(container);
108 main.add(scroll);
109 container.setLayout(layout);
110 container.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
111 c.gridx = 0;
112 c.gridy = -1;
113 c.anchor = GridBagConstraints.NORTHWEST;
114 c.fill = GridBagConstraints.NONE;
115
116 Iterator fields = form.getFields();
117 while (fields.hasNext()) {
118 FormField field = (FormField) fields.next();
119
120 Field f;
121
122 if (field.getType().equals(FormField.TYPE_BOOLEAN)) {
123 f = new BooleanField(field);
124 } else if (field.getType().equals(FormField.TYPE_FIXED)) {
125 f = new FixedField(field);
126 } else if (field.getType().equals(FormField.TYPE_HIDDEN)) {
127 f = new HiddenField(field);
128 } else if (field.getType().equals(FormField.TYPE_TEXT_MULTI)) {
129 f = new MultiTextField(field);
130 } else if (field.getType().equals(FormField.TYPE_TEXT_PRIVATE)) {
131 f = new PrivateField(field);
132 } else if (field.getType().equals(FormField.TYPE_LIST_SINGLE)
133 || field.getType().equals(FormField.TYPE_JID_SINGLE)) {
134 f = new ListSingleField(field);
135 } else if (field.getType().equals(FormField.TYPE_LIST_MULTI)
136 || field.getType().equals(FormField.TYPE_JID_MULTI)) {
137 f = new ListMultiField(field);
138 } else {
139 f = new Field(field);
140 }
141
142 this.fields.add(f);
143
144 if (!field.getType().equals(FormField.TYPE_HIDDEN)
145 && !field.getType().equals(FormField.TYPE_FIXED)) {
146 c.gridy++;
147 c.gridx = 0;
148 Component left = f.getLeftComponent();
149 Component right = f.getRightComponent();
150 c.fill = GridBagConstraints.HORIZONTAL;
151 c.weightx = .5;
152
153 layout.setConstraints(left, c);
154 container.add(left);
155
156 c.fill = GridBagConstraints.NONE;
157 c.gridx++;
158 c.weightx = .5;
159 layout.setConstraints(right, c);
160 container.add(right);
161 } else if (field.getType().equals(FormField.TYPE_FIXED)) {
162 c.gridy++;
163 c.gridx = 0;
164 c.gridwidth = 2;
165 JLabel label = new JLabel("<html><b>" + f.getFirstValue()
166 + "</b></html>");
167 layout.setConstraints(label, c);
168 container.add(label);
169 c.gridwidth = 1;
170 }
171 }
172
173 c.gridy++;
174 c.gridwidth = 2;
175 c.weighty = .9;
176 JLabel blank = new JLabel("");
177 layout.setConstraints(blank, c);
178 container.add(blank);
179
180 ActionListener listener = new ActionListener() {
181 public void actionPerformed(ActionEvent e) {
182 fireEvent(e);
183 }
184 };
185
186 okButton.setActionCommand("ok");
187 cancelButton.setActionCommand("cancel");
188 okButton.addActionListener(listener);
189 cancelButton.addActionListener(listener);
190
191 pack();
192 setSize(new Dimension(630, 450));
193 setLocationRelativeTo(parent);
194 }
195
196 public Form getAnswerForm() {
197 Form a = null;
198 try {
199 a = form.createAnswerForm();
200 } catch (Exception ex) {
201 Standard.warningMessage(this, resources.getString("dataForm"),
202 resources.getString("unknownError"));
203 dispose();
204 return null;
205 }
206
207 for (int i = 0; i < this.fields.size(); i++) {
208 Field field = (Field) this.fields.get(i);
209 if (field.getVariable() == null || field.getVariable().equals(""))
210 continue;
211
212 if (!ensureAnswer(field.getFormField(), field.getAnswer()))
213 return null;
214 Object answer = field.getAnswer();
215
216 //com.valhalla.Logger.debug( i + " " + field.getVariable() + " " +
217 // answer + " " + field.getFormField().getType() );
218
219 if (answer instanceof Boolean) {
220 a.setAnswer(field.getVariable(), ((Boolean) answer)
221 .booleanValue());
222 } else if (answer instanceof java.util.List) {
223 a.setAnswer(field.getVariable(), (java.util.List) answer);
224 } else {
225 a.setAnswer(field.getVariable(), (String) answer);
226 }
227 }
228
229 return a;
230 }
231
232 private boolean ensureAnswer(FormField field, Object answer) {
233 if (!field.isRequired())
234 return true;
235
236 if ((answer instanceof String && ((String) answer).equals(""))
237 || answer == null
238 || (answer instanceof java.util.List && ((java.util.List) answer)
239 .size() <= 0)) {
240 String w = MessageFormat.format(resources.getString("emptyField"),
241 new Object[] { field.getLabel() });
242 Standard.warningMessage(this, resources.getString(getTitle()), w);
243
244 return false;
245 }
246
247 return true;
248 }
249
250 public void addActionListener(ActionListener listener) {
251 listeners.add(listener);
252 }
253
254 private void fireEvent(ActionEvent e) {
255 for (int i = 0; i < listeners.size(); i++) {
256 ActionListener l = (ActionListener) listeners.get(i);
257 l.actionPerformed(e);
258 }
259 }
260 }
261
262 class Field {
263 protected JComponent rightComp = new MJTextField(15);
264
265 protected FormField field;
266
267 public Field(FormField field) {
268 this.field = field;
269 ((JTextField) rightComp).setText(getFirstValue());
270 }
271
272 public FormField getFormField() {
273 return field;
274 }
275
276 protected String getFirstValue() {
277 Iterator it = field.getValues();
278 if (!it.hasNext())
279 return "";
280 return (String) it.next();
281 }
282
283 public String getVariable() {
284 return field.getVariable();
285 }
286
287 public Object getAnswer() {
288 return ((JTextField) rightComp).getText();
289 }
290
291 public JComponent getLeftComponent() {
292 return new JLabel("<html>" + field.getLabel() + ":</html>");
293 }
294
295 public JComponent getRightComponent() {
296 return rightComp;
297 }
298 }
299
300 class MultiTextField extends Field {
301 private MJTextArea text = new MJTextArea(3, 20);
302
303 public MultiTextField(FormField field) {
304 super(field);
305 rightComp = new JScrollPane(text);
306 text.setText(getFirstValue());
307 }
308
309 public Object getAnswer() {
310 return text.getText();
311 }
312 }
313
314 class ListSingleField extends Field {
315 public ListSingleField(FormField field) {
316 super(field);
317
318 ArrayList list = new ArrayList();
319
320 Iterator options = field.getOptions();
321 int selected = -1;
322 int count = 0;
323 String def = getFirstValue();
324
325 while (options.hasNext()) {
326 FormField.Option option = (FormField.Option) options.next();
327 list.add(option);
328
329 if (option.getValue().equals(def))
330 selected = count;
331 count++;
332 }
333
334 rightComp = new JComboBox(list.toArray());
335 ((JComboBox) rightComp).setRenderer(new MyListRenderer());
336 if (selected != -1) {
337 ((JComboBox) rightComp).setSelectedIndex(selected);
338 }
339 }
340
341 public Object getAnswer() {
342 FormField.Option option = (FormField.Option) ((JComboBox) rightComp)
343 .getSelectedItem();
344 ArrayList answers = new ArrayList();
345 answers.add(option.getValue());
346 return answers;
347 }
348 }
349
350 class ListMultiField extends Field {
351 public ListMultiField(FormField field) {
352 super(field);
353
354 ArrayList list = new ArrayList();
355
356 Iterator options = field.getOptions();
357 ArrayList selected = new ArrayList();
358 int count = 0;
359
360 while (options.hasNext()) {
361 FormField.Option option = (FormField.Option) options.next();
362 list.add(option);
363
364 Iterator values = field.getValues();
365 while (values.hasNext()) {
366 String value = (String) values.next();
367 if (option.getValue().equals(value))
368 selected.add(new Integer(count));
369 }
370
371 count++;
372 }
373
374 rightComp = new JList(list.toArray());
375
376 if (selected.size() > 0) {
377 int indecis[] = new int[selected.size()];
378 for (int i = 0; i < selected.size(); i++) {
379 Integer in = (Integer) selected.get(i);
380 indecis[i] = in.intValue();
381 }
382 ((JList) rightComp).setSelectedIndices(indecis);
383 }
384
385 ((JList) rightComp).setCellRenderer(new MyListRenderer());
386 }
387
388 public Object getAnswer() {
389 Object[] sel = ((JList) rightComp).getSelectedValues();
390 ArrayList answers = new ArrayList();
391 for (int i = 0; i < sel.length; i++) {
392 FormField.Option option = (FormField.Option) sel[i];
393 answers.add(option.getValue());
394 }
395
396 return answers;
397 }
398 }
399
400 class PrivateField extends Field {
401 public PrivateField(FormField field) {
402 super(field);
403 rightComp = new JPasswordField(15);
404 ((JPasswordField) rightComp).setText(getFirstValue());
405 ((JPasswordField) rightComp).setFont(new MJTextField().getFont());
406 }
407
408 public Object getAnswer() {
409 return new String(((JPasswordField) rightComp).getPassword());
410 }
411 }
412
413 class HiddenField extends Field {
414 public HiddenField(FormField field) {
415 super(field);
416 }
417
418 public Object getAnswer() {
419 return getFirstValue();
420 }
421 }
422
423 class BooleanField extends Field {
424 public BooleanField(FormField field) {
425 super(field);
426 rightComp = new JCheckBox();
427
428 if (getFirstValue().equals("1"))
429 ((JCheckBox) rightComp).setSelected(true);
430 }
431
432 public Object getAnswer() {
433 if (((JCheckBox) rightComp).isSelected()) {
434 return new Boolean(true);
435 } else {
436 return new Boolean(false);
437 }
438 }
439 }
440
441 class FixedField extends Field {
442 public FixedField(FormField field) {
443 super(field);
444 }
445
446 public Object getAnswer() {
447 return getFirstValue();
448 }
449 }
450
451 class MyListRenderer extends JLabel implements ListCellRenderer {
452 public MyListRenderer() {
453 setOpaque(true);
454 }
455
456 public Component getListCellRendererComponent(JList list, Object value,
457 int index, boolean isSelected, boolean cellHasFocus) {
458 FormField.Option op = (FormField.Option) value;
459
460 if (!op.getLabel().equals("")) {
461 setText(op.getLabel());
462 } else {
463 setText(op.getValue());
464 }
465
466 setBackground(isSelected ? list.getSelectionBackground() : list
467 .getBackground());
468 setForeground(isSelected ? list.getSelectionForeground() : list
469 .getForeground());
470 return this;
471 }
472 }