Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.dynform / org.gvsig.tools.dynform.impl / src / main / java / org / gvsig / tools / dynform / impl / DefaultJDynForm.java @ 1149

History | View | Annotate | Download (23.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.tools.dynform.impl;
24

    
25
import java.awt.BorderLayout;
26
import java.awt.Component;
27
import java.awt.Dimension;
28
import java.awt.event.MouseAdapter;
29
import java.awt.event.MouseEvent;
30
import java.util.ArrayList;
31
import java.util.HashMap;
32
import java.util.HashSet;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Map;
36
import java.util.Set;
37

    
38
import javax.swing.Action;
39
import javax.swing.BorderFactory;
40
import javax.swing.JComponent;
41
import javax.swing.JLabel;
42
import javax.swing.JOptionPane;
43
import javax.swing.JPanel;
44
import javax.swing.JScrollPane;
45
import javax.swing.JTabbedPane;
46
import javax.swing.JViewport;
47

    
48
import org.apache.commons.lang3.StringUtils;
49
import org.gvsig.tools.ToolsLocator;
50
import org.gvsig.tools.dataTypes.CoercionException;
51
import org.gvsig.tools.dataTypes.DataType;
52
import org.gvsig.tools.dataTypes.DataTypes;
53
import org.gvsig.tools.dynform.DynFormDefinition;
54
import org.gvsig.tools.dynform.DynFormFieldDefinition;
55
import org.gvsig.tools.dynform.JDynForm;
56
import org.gvsig.tools.dynform.JDynFormField;
57
import org.gvsig.tools.dynform.JDynFormField.JDynFormFieldListener;
58
import org.gvsig.tools.dynform.spi.DynFormSPIManager;
59
import org.gvsig.tools.dynform.spi.dynformfield.SupportPopupMenu;
60
import org.gvsig.tools.dynobject.DynClass;
61
import org.gvsig.tools.dynobject.DynField;
62
import org.gvsig.tools.dynobject.DynField_v2;
63
import org.gvsig.tools.dynobject.DynObject;
64
import org.gvsig.tools.service.ServiceException;
65
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
67

    
68
import com.jgoodies.forms.builder.DefaultFormBuilder;
69
import com.jgoodies.forms.layout.FormLayout;
70
import com.jgoodies.forms.layout.RowSpec;
71
import java.util.Collection;
72
import java.util.Map.Entry;
73
import org.gvsig.tools.dynform.spi.dynformfield.AbstractJDynFormField;
74

    
75
@SuppressWarnings({"unchecked", "rawtypes"})
76
public class DefaultJDynForm implements JDynForm, JDynFormFieldListener {
77

    
78
    protected static final Logger logger = LoggerFactory
79
            .getLogger(DefaultJDynForm.class);
80

    
81
    private int formWidth = 320;
82
    private int formHeight = 540;
83

    
84
    private DefaultDynFormManager manager = null;
85
    private DynFormDefinition definition = null;
86
    private int layoutMode = USE_PLAIN;
87
    private JComponent contents = null;
88
    private Map components = null;
89
    private JLabel jlabel_messages = null;
90
    private boolean readOnly = false;
91
    private Set listeners = null;
92
    private DynObject values = null;
93
    private boolean useScrollBars = true;
94

    
95
    private Map customActions;
96

    
97
    public DefaultJDynForm(DefaultDynFormManager manager, DynFormDefinition definition) throws ServiceException {
98
        this.manager = manager;
99
        this.definition = definition;
100
        this.components = new HashMap();
101
        this.listeners = new HashSet();
102
        this.customActions = new HashMap<String, List<Action>>();
103
        if (definition.getTags().has("LayoutMode")) {
104
            try {
105
                this.layoutMode = definition.getTags().getInt("LayoutMode");
106
            } catch (CoercionException e) {
107
                // Ignorada
108
            }
109
        }
110
    }
111

    
112
    public DynFormSPIManager getServiceManager() {
113
        return this.manager.getServiceManager();
114
    }
115

    
116
    public JComponent asJComponent() {
117
        if (this.contents == null) {
118
            try {
119
                this.initComponents();
120
            } catch (ServiceException e) {
121
                throw new RuntimeException(e.getLocalizedMessage(), e);
122
            }
123
        }
124
        return this.contents;
125
    }
126

    
127
    public void addListener(JDynFormListener listener) {
128
        this.listeners.add(listener);
129
    }
130

    
131
    public void removeListener(JDynFormListener listener) {
132
        this.listeners.remove(listener);
133
    }
134

    
135
    protected void fireMessageEvent(String message) {
136
        Iterator it = this.listeners.iterator();
137
        while (it.hasNext()) {
138
            JDynFormListener listener = (JDynFormListener) it.next();
139
            try {
140
                listener.message(message);
141
            } catch (Exception ex) {
142
                logger.info("Error calling listener " + listener.toString()
143
                        + "(" + listener.getClass().getName() + ") from "
144
                        + this.toString() + "(" + this.getClass().getName()
145
                        + ").", ex);
146
            }
147
        }
148
    }
149

    
150
    protected void fireFieldChangeEvent(JDynFormField field) {
151
        Iterator it = this.listeners.iterator();
152
        while (it.hasNext()) {
153
            JDynFormListener listener = (JDynFormListener) it.next();
154
            try {
155
                listener.fieldChanged(field);
156
            } catch (Exception ex) {
157
                logger.info("Error calling listener " + listener.toString()
158
                        + "(" + listener.getClass().getName() + ") from "
159
                        + this.toString() + "(" + this.getClass().getName()
160
                        + ").", ex);
161
            }
162
        }
163
    }
164

    
165
    public JLabel getMessagesJLabel() {
166
        if (this.jlabel_messages == null) {
167
            this.jlabel_messages = new JLabel();
168
            this.jlabel_messages.addMouseListener(new MouseAdapter() {
169
                public void mouseClicked(MouseEvent evt) {
170
                    int count = evt.getClickCount();
171
                    if (count == 2) {
172
                        JOptionPane.showMessageDialog(contents, jlabel_messages.getText(), "Status", JOptionPane.INFORMATION_MESSAGE);
173
                    }
174
                }
175
            });
176
        }
177
        return this.jlabel_messages;
178
    }
179

    
180
    public void setShowMessageStatus(boolean showMessageStatus) {
181
        this.getMessagesJLabel().setVisible(showMessageStatus);
182
    }
183

    
184
    public boolean isShowMessageStatus() {
185
        return this.getMessagesJLabel().isVisible();
186
    }
187

    
188
    public void message() {
189
        this.getMessagesJLabel().setText(" ");
190
    }
191

    
192
    public void message(String msg) {
193
        this.getMessagesJLabel().setText(msg);
194
        fireMessageEvent(msg);
195
    }
196

    
197
    private void initComponents() throws ServiceException {
198
        switch (this.layoutMode) {
199
            case USE_PLAIN:
200
            case USE_TREE:
201
            default:
202
                initComponentsPlain();
203
                break;
204
            case USE_TABS:
205
                initComponentsUseTabs();
206
                break;
207
            case USE_SEPARATORS:
208
                initComponentsUseSeparators();
209
                break;
210
        }
211
        if (this.values != null) {
212
            this.setValues(values);
213
        }
214
        message();
215
    }
216

    
217
    private void initComponentsPlain() throws ServiceException {
218
        FormLayout layout = new FormLayout(
219
                "left:pref,  8px,  fill:80dlu:grow", "pref");
220

    
221
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
222
        builder.setDefaultRowSpec(new RowSpec(
223
                RowSpec.TOP,
224
                builder.getLayout().getRowSpec(1).getSize(),
225
                builder.getLayout().getRowSpec(1).getResizeWeight()));
226

    
227
        List fields = this.definition.getDefinitions();
228
        Iterator it = fields.iterator();
229
        while (it.hasNext()) {
230
            DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
231
            if (fieldDefinition.isHidden()) {
232
                continue;
233
            }
234
            JDynFormField jfield = getServiceManager().createJDynFormField(fieldDefinition, null);
235
            if( jfield instanceof AbstractJDynFormField ) {
236
                ((AbstractJDynFormField)jfield).setForm(this);
237
            }
238
            jfield.setReadOnly(this.readOnly);
239
            jfield.addListener(this);
240
            if (this.readOnly) {
241
                jfield.setReadOnly(readOnly);
242
            }
243
            builder.append(jfield.getJLabel(), jfield.asJComponent());
244

    
245
            this.components.put(jfield.getName(), jfield);
246
        }
247
        this.contents = addScrollsAndMessageBar(builder.getPanel());
248
    }
249

    
250
    private void initComponentsUseSeparators() throws ServiceException {
251
        List groups = this.definition.getGroups();
252

    
253
        FormLayout layout = new FormLayout(
254
                "left:pref,  8px,  fill:80dlu:grow", "pref");
255

    
256
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
257
        builder.setDefaultRowSpec(new RowSpec(
258
                RowSpec.TOP,
259
                builder.getLayout().getRowSpec(1).getSize(),
260
                builder.getLayout().getRowSpec(1).getResizeWeight()));
261

    
262
        for (int i = 0; i < groups.size(); i++) {
263
            String group = (String) groups.get(i);
264
            builder.appendSeparator(group);
265
            List fields = this.definition.getDefinitions(group);
266
            Iterator it = fields.iterator();
267
            while (it.hasNext()) {
268
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
269
                if (fieldDefinition.isHidden()) {
270
                    continue;
271
                }
272
                JDynFormField jfield = getServiceManager().createJDynFormField(fieldDefinition, null);
273
                if( jfield instanceof AbstractJDynFormField ) {
274
                    ((AbstractJDynFormField)jfield).setForm(this);
275
                }
276
                jfield.addListener(this);
277
                if (this.readOnly) {
278
                    jfield.setReadOnly(readOnly);
279
                }
280

    
281
                List<Action> customActions = getCustomFields(fieldDefinition.getDataType());
282

    
283
                if (customActions != null && !customActions.isEmpty()) {
284
                    Iterator it2 = customActions.iterator();
285
                    while (it2.hasNext()) {
286
                        Object obj = it2.next();
287
                        if (obj != null) {
288
                            Action act = (Action) obj;
289
                            jfield.addActionToPopupMenu((String) act.getValue(Action.NAME), act);
290
                        } else {
291
                            jfield.addSeparatorToPopupMenu();
292
                        }
293
                    }
294
                }
295

    
296
                builder.append(jfield.getJLabel(), jfield.asJComponent());
297

    
298
                this.components.put(jfield.getName(), jfield);
299
            }
300
        }
301
        this.contents = addScrollsAndMessageBar(builder.getPanel());
302
    }
303

    
304
    private void initComponentsUseTabs() throws ServiceException {
305

    
306
        JTabbedPane tabbedPane = new JTabbedPane();
307
        if (definition.getTags().has("TabPlacement")) {
308
            try {
309
                tabbedPane.setTabPlacement(definition.getTags().getInt("TabPlacement"));
310
            } catch (Exception e) {
311
                // Ignorada
312
            }
313
        }
314
        List groups = this.definition.getGroups();
315

    
316
        for (int i = 0; i < groups.size(); i++) {
317
            String group = (String) groups.get(i);
318

    
319
            FormLayout layout = new FormLayout(
320
                    "left:pref,  8px,  fill:80dlu:grow", "pref");
321

    
322
            DefaultFormBuilder builder = new DefaultFormBuilder(layout);
323
            builder.setDefaultRowSpec(new RowSpec(
324
                    RowSpec.TOP,
325
                    builder.getLayout().getRowSpec(1).getSize(),
326
                    builder.getLayout().getRowSpec(1).getResizeWeight()));
327

    
328
            List fields = this.definition.getDefinitions(group);
329
            Iterator it = fields.iterator();
330
            while (it.hasNext()) {
331
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
332
                if (fieldDefinition.isHidden()) {
333
                    continue;
334
                }
335
                JDynFormField jfield = getServiceManager().createJDynFormField(fieldDefinition, null);
336
                if( jfield instanceof AbstractJDynFormField ) {
337
                    ((AbstractJDynFormField)jfield).setForm(this);
338
                }
339
                jfield.setReadOnly(this.readOnly);
340
                jfield.addListener(this);
341
                if (this.readOnly) {
342
                    jfield.setReadOnly(readOnly);
343
                }
344

    
345
                builder.append(jfield.getJLabel(), jfield.asJComponent());
346

    
347
                this.components.put(jfield.getName(), jfield);
348
            }
349
            String tablabel = group;
350
            if (StringUtils.isEmpty(tablabel)) {
351
                tablabel = ToolsLocator.getI18nManager().getTranslation("General");
352
            }
353
            tabbedPane.addTab(tablabel, builder.getPanel());
354
        }
355
        this.contents = addScrollsAndMessageBar(tabbedPane);
356
    }
357

    
358
    private List<Action> getCustomFields(DataType dataType) {
359
        return (List<Action>) customActions.get(dataType.getName());
360
    }
361

    
362
    private JPanel addScrollsAndMessageBar(JComponent formPanel) {
363
        formPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
364
        JScrollPane scroll = new JScrollPane(formPanel);
365
        if (useScrollBars) {
366
            scroll.setPreferredSize(new Dimension(formWidth, formHeight));
367
        } else {
368
            scroll.setPreferredSize(formPanel.getPreferredSize());
369
        }
370
        scroll.setBorder(BorderFactory.createEmptyBorder());
371

    
372
        JPanel jpanel = new JPanel();
373
        jpanel.setLayout(new BorderLayout());
374
        jpanel.add(scroll, BorderLayout.CENTER);
375
        jpanel.add(getMessagesJLabel(), BorderLayout.PAGE_END);
376

    
377
        return jpanel;
378
    }
379

    
380
    public int getLayoutMode() {
381
        return this.layoutMode;
382
    }
383

    
384
    public void setLayoutMode(int layoutMode) {
385
        if (layoutMode < 0 || layoutMode > USE_SEPARATORS) {
386
            throw new IllegalArgumentException("layoutMode (" + layoutMode + ") out of range. Valid values are 0 .. " + USE_SEPARATORS + ".");
387
        }
388
        this.layoutMode = layoutMode;
389
    }
390

    
391
    public void setValues(DynObject values) {
392
        /*
393
         * TODO: Probablemente fuese mas acertado recorrer los controles de
394
         * components y a partir de ellos acceder a los valores del DynObject
395
         * recivido. Eso permitiria trabajar mejor con herencia de DynObject.
396
         * Habria que hacer lo mismo con el getValues. 
397
         */
398
        if (this.contents == null) {
399
            this.values = values;
400
            return;
401
        }
402
        DynClass def = values.getDynClass();
403
        DynField[] fields = def.getDynFields();
404
        for (int i = 0; i < fields.length; i++) {
405
            String name = fields[i].getName();
406
            if (name == null || name.isEmpty()) {
407
                logger.warn("Field name " + i + " of '" + def.getFullName() + "' is null or empty ");
408
                continue;
409
            }
410
            JDynFormField jfield = (JDynFormField) this.getField(name);
411
            if (jfield == null) {
412
                logger.warn("Can't retrieve form field asociated to the field '" + name + "' of class '" + def.getFullName() + "'.");
413
                continue;
414
            }
415
            if (values.getDynValue(name) == null) {
416
                if (fields[i].getDataType().getType() == DataTypes.LIST) {
417
                    try {
418
                        if (((DynField_v2) fields[i]).getDynClassOfItems() != null) {
419
                            values.setDynValue(name, new ArrayList<DynObject>());
420
                        }
421
                    } catch (Exception e) {
422
                        logger.warn("Problems initializing the DynObject List", e);
423
                    }
424
                }
425
            }
426
            jfield.setValue(values.getDynValue(name));
427
        }
428
    }
429

    
430
    public void getValues(DynObject values) {
431
        if (values == null) {
432
            return;
433
        }
434
        DynField[] fields = values.getDynClass().getDynFields();
435
        for (int i = 0; i < fields.length; i++) {
436
            String name = fields[i].getName();
437
            JDynFormField jfield = (JDynFormField) this.getField(name);
438
            if (jfield != null) {
439
                try {
440
                    Object value = jfield.getValue();
441
                    values.setDynValue(name, value);
442

    
443
                } catch (Exception ex) {
444
                    logger.warn("Can't get value of field '" + name + "'.", ex);
445
                }
446
            }
447
        }
448
    }
449

    
450
    public boolean hasValidValues() {
451
        Iterator it = this.getFieldsIterator();
452
        while (it.hasNext()) {
453
            JDynFormField jfield = (JDynFormField) it.next();
454
            if (!jfield.hasValidValue()) {
455
                return false;
456
            }
457
        }
458

    
459
        return true;
460
    }
461

    
462
    public boolean hasValidValues(List<String> fieldsName) {
463
        if (fieldsName == null) {
464
            fieldsName = new ArrayList<String>();
465
        }
466

    
467
        Iterator it = this.getFieldsIterator();
468
        while (it.hasNext()) {
469
            JDynFormField jfield = (JDynFormField) it.next();
470
            if (!jfield.hasValidValue()) {
471
                fieldsName.add(jfield.getName());
472
            }
473
        }
474

    
475
        if (!fieldsName.isEmpty()) {
476
            return false;
477
        } else {
478
            return true;
479
        }
480
    }
481

    
482
    public boolean isModified() {
483
        Iterator it = this.getFieldsIterator();
484
        while (it.hasNext()) {
485
            JDynFormField jfield = (JDynFormField) it.next();
486
            if (jfield.isModified()) {
487
                return true;
488
            }
489
        }
490
        return false;
491
    }
492

    
493
    public void fieldEnter(JDynFormField field) {
494
        message(field.getDefinition().getDescription());
495
    }
496

    
497
    public void fieldExit(JDynFormField field) {
498
        message();
499
    }
500

    
501
    public void message(JDynFormField field, String message) {
502
        message(message);
503
    }
504

    
505
    public void fieldChanged(JDynFormField field) {
506
        fireFieldChangeEvent(field);
507
    }
508

    
509
    public boolean isReadOnly() {
510
        return readOnly;
511
    }
512

    
513
    public void setReadOnly(boolean readOnly) {
514
        this.readOnly = readOnly;
515
        if (this.contents != null) {
516
            Iterator it = this.getFieldsIterator();
517
            while (it.hasNext()) {
518
                JDynFormField field = (JDynFormField) it.next();
519
                field.setReadOnly(readOnly);
520
            }
521
        }
522
    }
523

    
524
    public int getFormWidth() {
525
        if (this.contents == null) {
526
            return this.formWidth;
527
        } else {
528
            JViewport port = ((JScrollPane) this.asJComponent()).getViewport();
529
            Component comp = (Component) port.getView();
530
            return comp.getWidth();
531
        }
532
    }
533

    
534
    public int getFormHeight() {
535
        if (this.contents == null) {
536
            return this.formHeight;
537
        } else {
538
            JViewport port = ((JScrollPane) this.asJComponent()).getViewport();
539
            Component comp = (Component) port.getView();
540
            return comp.getHeight();
541
        }
542
    }
543

    
544
    public void setFormSize(int width, int height) {
545
        this.formHeight = height;
546
        this.formWidth = width;
547
        if (this.contents != null) {
548
            this.asJComponent().setPreferredSize(new Dimension(width, height));
549
        }
550
    }
551

    
552
    public void addActionToPopupMenu(DataType tipo, String name, Action action) {
553
        if (this.contents == null) {
554
            List<Action> acts = this.getCustomFields(tipo);
555
            action.putValue(Action.NAME, name);
556
            if (acts == null) {
557
                List aux = new ArrayList<Action>();
558
                aux.add(action);
559
                customActions.put(tipo.getName(), aux);
560
            } else {
561
                acts.add(action);
562
            }
563
        } else {
564
            Iterator it = this.components.keySet().iterator();
565
            while (it.hasNext()) {
566
                String key = (String) it.next();
567
                Object obj = this.components.get(key);
568
                if (obj instanceof JDynFormField) {
569
                    JDynFormField field = (JDynFormField) obj;
570
                    if (tipo == field.getDefinition().getDataType()) {
571
                        if (field.asJComponent() instanceof SupportPopupMenu) {
572
                            field.addActionToPopupMenu(
573
                                    name,
574
                                    action);
575
                        }
576
                    }
577
                }
578
            }
579
        }
580
    }
581

    
582
    public void addSeparatorToPopupMenu(DataType tipo) {
583
        if (this.contents == null) {
584
            List<Action> acts = this.getCustomFields(tipo);
585
            if (acts == null) {
586
                List aux = new ArrayList<Action>();
587
                aux.add(null);
588
                customActions.put(tipo.getName(), aux);
589
            } else {
590
                acts.add(null);
591
            }
592
        } else {
593
            Iterator it = this.components.keySet().iterator();
594
            while (it.hasNext()) {
595
                String key = (String) it.next();
596
                Object obj = this.components.get(key);
597
                if (obj instanceof JDynFormField) {
598
                    JDynFormField field = (JDynFormField) obj;
599
                    if (tipo == field.getDefinition().getDataType()) {
600
                        if (field.asJComponent() instanceof SupportPopupMenu) {
601
                            ((SupportPopupMenu) field.asJComponent()).addSeparatorToPopupMenu();
602
                        }
603
                    }
604
                }
605
            }
606
        }
607
    }
608

    
609
    public Object getValue(String fieldName) {
610
        JDynFormField field = (JDynFormField) this.getField(fieldName);
611
        return field.getValue();
612
    }
613

    
614
    public void setValue(String fieldName, Object value) {
615
        JDynFormField field = (JDynFormField) this.getField(fieldName);
616
        try {
617
            value = field.getDefinition().getDataType().coerce(value);
618
        } catch (CoercionException e) {
619
            String msg = "Invalid value '" + ((value == null) ? "(null)" : value.toString()) + "' for field '" + fieldName + "'.";
620
            logger.warn(msg, e);
621
            throw new RuntimeException(msg, e);
622
        }
623
        field.setValue(value);
624
    }
625

    
626
    public JDynFormField getField(String fieldName) {
627
        JDynFormField field = (JDynFormField) this.components.get(fieldName);
628
        return field;
629
    }
630

    
631
    public Iterator getFieldsIterator() {
632
        if (this.contents == null) {
633
            try {
634
                this.initComponents();
635
            } catch (ServiceException e) {
636
                throw new RuntimeException(e.getLocalizedMessage(), e);
637
            }
638
        }
639
        return this.components.values().iterator();
640
    }
641

    
642
    public DynFormDefinition getDefinition() {
643
        return this.definition;
644
    }
645

    
646
    public void setUseScrollBars(boolean usesScrolls) {
647
        this.useScrollBars = usesScrolls;
648
    }
649

    
650
    public boolean getUseScrollBars() {
651
        return useScrollBars;
652
    }
653

    
654
    public void clear() {
655
        Iterator it = this.components.entrySet().iterator();
656
        while( it.hasNext() ) {
657
            Entry entry = (Entry)it.next();
658
            ((JDynFormField)(entry.getValue())).clear();
659
        }
660
    }
661

    
662
    public Collection getShowFields() {
663
        return this.components.values();
664
    }
665

    
666
    
667
    
668
}