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    }