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 @ 1948

History | View | Annotate | Download (21.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 org.gvsig.tools.dynform.spi.dynform.AbstractJDynForm;
26
import java.util.ArrayList;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.Map;
31

    
32
import javax.swing.Action;
33
import javax.swing.JComponent;
34
import javax.swing.JTabbedPane;
35

    
36
import org.apache.commons.lang3.StringUtils;
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dataTypes.CoercionException;
39
import org.gvsig.tools.dataTypes.DataType;
40
import org.gvsig.tools.dataTypes.DataTypes;
41
import org.gvsig.tools.dynform.DynFormDefinition;
42
import org.gvsig.tools.dynform.DynFormFieldDefinition;
43
import org.gvsig.tools.dynform.JDynFormField;
44
import org.gvsig.tools.dynform.JDynFormField.JDynFormFieldListener;
45
import org.gvsig.tools.dynform.spi.dynformfield.SupportPopupMenu;
46
import org.gvsig.tools.dynobject.DynClass;
47
import org.gvsig.tools.dynobject.DynField;
48
import org.gvsig.tools.dynobject.DynField_v2;
49
import org.gvsig.tools.dynobject.DynObject;
50
import org.gvsig.tools.service.ServiceException;
51

    
52
import com.jgoodies.forms.builder.DefaultFormBuilder;
53
import com.jgoodies.forms.layout.FormLayout;
54
import com.jgoodies.forms.layout.RowSpec;
55
import java.util.Collection;
56
import org.gvsig.tools.dynform.spi.DynFormSPIManager;
57
import org.gvsig.tools.dynform.spi.DynFormSPIManager.ComponentsFactory;
58
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.TAG_DYNFORM_SEPARATOR;
59
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_CLEAR;
60
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ISMODIFIED;
61
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ISREADONLY;
62
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONFIELDCHANGED;
63
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONFIELDENTER;
64
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONFIELDEXIT;
65
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONLOAD;
66
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONSETVALUES;
67
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_VALIDATE;
68
import org.gvsig.tools.dynform.spi.dynform.JDynFormFactory;
69
import org.gvsig.tools.dynform.spi.dynformfield.JDynFormFieldFactory;
70
import org.gvsig.tools.dynform.spi.dynformfield.AbstractJDynFormField;
71
import org.gvsig.tools.dynobject.Tags;
72
import org.gvsig.tools.i18n.I18nManager;
73

    
74
@SuppressWarnings("UseSpecificCatch")
75
public class DefaultJDynForm extends AbstractJDynForm implements JDynFormFieldListener {
76

    
77
    private Map components = null;
78
    private ComponentsFactory componentsFactory;
79

    
80
    public DefaultJDynForm(
81
            DynFormSPIManager manager, 
82
            JDynFormFactory factory,
83
            DynFormDefinition definition,
84
            DynFormContext context
85
        ) {
86
        super(manager, factory, definition, context);
87
        this.components = new HashMap();
88
        this.componentsFactory = manager.createDefaultComponentsFactory();
89
    }
90

    
91
    @Override
92
    protected JComponent getFieldsContainer() {
93

    
94
        try {
95
            JComponent component;
96
            switch (this.getLayoutMode()) {
97
                case USE_PLAIN:
98
                case USE_TREE:
99
                default:
100
                    component = getFieldsContainerPlain();
101
                    break;
102
                case USE_TABS:
103
                    component = getFieldsContainerUseTabs();
104
                    break;
105
                case USE_SEPARATORS:
106
                    component = getFieldsContainerUseSeparators();
107
                    break;
108
            }
109
            this.callUserEvent(USERCODE_FORM_ONLOAD, this);
110
            return component;
111
        } catch (ServiceException ex) {
112
            throw new RuntimeException(ex);
113
        }
114
    }
115

    
116
    private JComponent getFieldsContainerPlain() throws ServiceException {
117
        FormLayout layout = new FormLayout(
118
                "left:pref,  8px,  fill:80dlu:grow", "pref");
119

    
120
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
121
        builder.setDefaultRowSpec(new RowSpec(
122
                RowSpec.TOP,
123
                builder.getLayout().getRowSpec(1).getSize(),
124
                builder.getLayout().getRowSpec(1).getResizeWeight()));
125

    
126
        List fields = this.getDefinition().getDefinitions();
127
        Iterator it = fields.iterator();
128
        while (it.hasNext()) {
129
            DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
130
            if (fieldDefinition.isHidden()) {
131
                continue;
132
            }
133
            JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
134
                    this.getContext(),
135
                    fieldDefinition
136
            );
137
            JDynFormField jfield = factory.create(
138
                    getServiceManager(), 
139
                    this.componentsFactory,
140
                    fieldDefinition, 
141
                    null
142
            );
143
            if (jfield instanceof AbstractJDynFormField) {
144
                ((AbstractJDynFormField) jfield).setForm(this);
145
            }
146
            if (this.isReadOnly()) {
147
                jfield.setReadOnly(true);
148
            } else {
149
                jfield.setReadOnly(fieldDefinition.isReadOnly());
150
            }
151
            jfield.addListener(this);
152
            builder.append(jfield.getJLabel(), jfield.asJComponent());
153

    
154
            this.components.put(jfield.getName(), jfield);
155
        }
156
        return builder.getPanel();
157
    }
158

    
159
    private JComponent getFieldsContainerUseSeparators() throws ServiceException {
160
        List<String> groups = this.getDefinition().getGroups();
161

    
162
        FormLayout layout = new FormLayout(
163
                "left:pref,  8px,  fill:80dlu:grow", "pref");
164

    
165
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
166
        builder.setDefaultRowSpec(new RowSpec(
167
                RowSpec.TOP,
168
                builder.getLayout().getRowSpec(1).getSize(),
169
                builder.getLayout().getRowSpec(1).getResizeWeight()));
170

    
171
        for (String group : groups) {
172
            boolean firstfield = true;
173
            List fields = this.getDefinition().getDefinitions(group);
174
            Iterator it = fields.iterator();
175
            while (it.hasNext()) {
176
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
177
                if (fieldDefinition.isHidden()) {
178
                    continue;
179
                }
180
                JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
181
                        this.getContext(),
182
                        fieldDefinition
183
                );
184
                JDynFormField jfield = factory.create(
185
                        getServiceManager(), 
186
                        this.componentsFactory,
187
                        fieldDefinition, 
188
                        null
189
                );
190
                if (jfield instanceof AbstractJDynFormField) {
191
                    ((AbstractJDynFormField) jfield).setForm(this);
192
                }
193
                jfield.addListener(this);
194
                if (this.isReadOnly()) {
195
                    jfield.setReadOnly(this.isReadOnly());
196
                }
197

    
198
                List<Action> customActions = getCustomFields(fieldDefinition.getDataType());
199

    
200
                if (customActions != null && !customActions.isEmpty()) {
201
                    Iterator it2 = customActions.iterator();
202
                    while (it2.hasNext()) {
203
                        Object obj = it2.next();
204
                        if (obj != null) {
205
                            Action act = (Action) obj;
206
                            jfield.addActionToPopupMenu((String) act.getValue(Action.NAME), act);
207
                        } else {
208
                            jfield.addSeparatorToPopupMenu();
209
                        }
210
                    }
211
                }
212
                if( firstfield ) {
213
                    firstfield = false;
214
                    builder.appendSeparator(group);
215
                }
216
                builder.append(jfield.getJLabel(), jfield.asJComponent());
217

    
218
                this.components.put(jfield.getName(), jfield);
219
            }
220
        }
221
        return builder.getPanel();
222
    }
223

    
224
    private JComponent getFieldsContainerUseTabs() throws ServiceException {
225

    
226
        JTabbedPane tabbedPane = new JTabbedPane();
227
        tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
228
        if (this.getDefinition().getTags().has("TabPlacement")) {
229
            try {
230
                tabbedPane.setTabPlacement(this.getDefinition().getTags().getInt("TabPlacement"));
231
            } catch (Exception e) {
232
                // Ignorada
233
            }
234
        }
235
        I18nManager i18n = ToolsLocator.getI18nManager();
236
        List<String> groups = this.getDefinition().getGroups();
237
        for (String group : groups) {
238
            FormLayout layout = new FormLayout(
239
                    "left:pref,  8px,  fill:80dlu:grow", "pref");
240
            DefaultFormBuilder builder = new DefaultFormBuilder(layout);
241
            builder.defaultRowSpec(new RowSpec(
242
                    RowSpec.TOP,
243
                    builder.getLayout().getRowSpec(1).getSize(),
244
                    builder.getLayout().getRowSpec(1).getResizeWeight()));
245
            List fields = this.getDefinition().getDefinitions(group);
246
            boolean hasFields = false;
247
            Iterator it = fields.iterator();
248
            while (it.hasNext()) {
249
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
250
                if (fieldDefinition.isHidden()) {
251
                    continue;
252
                }
253
                JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
254
                        this.getContext(),
255
                        fieldDefinition
256
                );
257
                JDynFormField jfield = factory.create(
258
                        getServiceManager(), 
259
                        this.componentsFactory,
260
                        fieldDefinition, 
261
                        null
262
                );
263
                if (jfield instanceof AbstractJDynFormField) {
264
                    ((AbstractJDynFormField) jfield).setForm(this);
265
                }
266
                jfield.setReadOnly(this.isReadOnly());
267
                jfield.addListener(this);
268
                if (this.isReadOnly()) {
269
                    jfield.setReadOnly(this.isReadOnly());
270
                }
271
                hasFields = true;
272
                Tags tags = jfield.getDefinition().getTags();
273
                if( tags!=null ) {
274
                    String sep = tags.getString(TAG_DYNFORM_SEPARATOR, null);
275
                    if( !StringUtils.isBlank(sep) ) {
276
                        builder.appendSeparator(i18n.getTranslation(sep));
277
                    }
278
                }                
279
                builder.append(jfield.getJLabel(), jfield.asJComponent());
280

    
281
                this.components.put(jfield.getName(), jfield);
282
            }
283
            if( hasFields ) {
284
                String tablabel = group;
285
                if (StringUtils.isEmpty(tablabel)) {
286
                    tablabel = ToolsLocator.getI18nManager().getTranslation("General");
287
                }
288
                tablabel = i18n.getTranslation(tablabel);
289
                tabbedPane.addTab(tablabel, builder.getPanel());
290
            }
291
        }
292

    
293
        try {
294
            String defaultGroupName = (String) this.getDefinition().getTags().get("defaultGroup", DataTypes.STRING);
295
            List<String> groupsNames = this.getDefinition().getGroups();
296
            int groupIndex = groupsNames.indexOf(defaultGroupName);
297
            if (groupIndex >= 0) {
298
                tabbedPane.setSelectedIndex(groupIndex);
299
            }
300
        } catch (Exception ex) {
301
            // Ignore errors and don't set a tab by default
302
        }
303

    
304
        return tabbedPane;
305
    }
306

    
307
    @Override
308
    public void setReadOnly(boolean readOnly) {
309
        if( this.isReadOnly() == readOnly ) {
310
            return;
311
        }
312
        super.setReadOnly(readOnly);
313
        if (this.isContentsInitialized()) {
314
            Iterator it = this.getFieldsIterator();
315
            while (it.hasNext()) {
316
                JDynFormField field = (JDynFormField) it.next();
317
                if( readOnly ) {
318
                    field.setReadOnly(true);
319
                } else if( field.getDefinition().isReadOnly() ) {
320
                    field.setReadOnly(true);
321
                } else {
322
                    field.setReadOnly(false);
323
                }
324
            }
325
        }
326
    }
327

    
328
    @Override
329
    public void setValues(DynObject values) {
330
        /*
331
         * TODO: Probablemente fuese mas acertado recorrer los controles de
332
         * components y a partir de ellos acceder a los valores del DynObject
333
         * recibido. Eso permitiria trabajar mejor con herencia de DynObject.
334
         * Habria que hacer lo mismo con el getValues.
335
         */
336
        if (!this.isContentsInitialized()) {
337
            this.values = values;
338
            return;
339
        }
340
        DynClass def = values.getDynClass();
341
        DynField[] fields = def.getDynFields();
342
        for (int i = 0; i < fields.length; i++) {
343
            DynField field = fields[i];
344
            if( field.isHidden() ) {
345
                continue;
346
            }
347
            String name = field.getName();
348
            if (name == null || name.isEmpty()) {
349
                LOGGER.warn("Field name " + i + " of '" + def.getFullName() + "' is null or empty ");
350
                continue;
351
            }
352
            JDynFormField jfield = (JDynFormField) this.getField(name);
353
            if (jfield == null) {
354
                LOGGER.warn("Can't retrieve form field asociated to the field '" + name + "' of class '" + def.getFullName() + "'.");
355
                continue;
356
            }
357
            if (values.getDynValue(name) == null) {
358
                if (fields[i].getDataType().getType() == DataTypes.LIST) {
359
                    try {
360
                        if (((DynField_v2) fields[i]).getDynClassOfItems() != null) {
361
                            values.setDynValue(name, new ArrayList<>());
362
                        }
363
                    } catch (Exception e) {
364
                        LOGGER.warn("Problems initializing the DynObject List", e);
365
                    }
366
                }
367
            }
368
            jfield.setValue(values.getDynValue(name));
369
        }
370
        this.callUserEvent(USERCODE_FORM_ONSETVALUES, this);
371
        try {
372
            if( (boolean) this.callUserFunction(USERCODE_FORM_ISREADONLY, this, values) ) {
373
                this.setReadOnly(true);
374
            }
375
        } catch (Exception ex) {
376
        }
377
    }
378

    
379
    @Override
380
    public void getValues(DynObject values) {
381
        if (values == null) {
382
            return;
383
        }
384
        DynField[] fields = values.getDynClass().getDynFields();
385
        for (DynField field : fields) {
386
            String name = field.getName();
387
            JDynFormField jfield = (JDynFormField) this.getField(name);
388
            if (jfield != null && !jfield.isReadOnly()) {
389
                try {
390
                    jfield.fetch(values);
391
                } catch (Exception ex) {
392
                    LOGGER.warn("Can't get value of field '" + name + "'.", ex);
393
                }
394
            }
395
        }
396
    }
397

    
398
    @Override
399
    public boolean hasValidValues() {
400
        Iterator it = this.getFieldsIterator();
401
        while (it.hasNext()) {
402
            JDynFormField jfield = (JDynFormField) it.next();
403
            if (!jfield.hasValidValue()) {
404
                return false;
405
            }
406
        }
407
        try {
408
            return (boolean) this.callUserFunction(USERCODE_FORM_VALIDATE, this);
409
        } catch (Exception ex) {
410
        }
411
        return true;
412
    }
413

    
414
    @Override
415
    public boolean hasValidValues(List<String> fieldsName) {
416
        if (fieldsName == null) {
417
            fieldsName = new ArrayList<>();
418
        }
419
        Iterator it = this.getFieldsIterator();
420
        while (it.hasNext()) {
421
            JDynFormField jfield = (JDynFormField) it.next();
422
            if (!jfield.hasValidValue()) {
423
                fieldsName.add(jfield.getName());
424
            }
425
        }
426
        return fieldsName.isEmpty();
427
    }
428

    
429
    @Override
430
    public Object getValue(String fieldName) {
431
        JDynFormField field = (JDynFormField) this.getField(fieldName);
432
        return field.getValue();
433
    }
434

    
435
    @Override
436
    public void setValue(String fieldName, Object value) {
437
        JDynFormField field = (JDynFormField) this.getField(fieldName);
438
        try {
439
            value = field.getDefinition().getDataType().coerce(value);
440
        } catch (CoercionException e) {
441
            String msg = "Invalid value '" + ((value == null) ? "(null)" : value.toString()) + "' for field '" + fieldName + "'.";
442
            LOGGER.warn(msg, e);
443
            throw new RuntimeException(msg, e);
444
        }
445
        field.setValue(value);
446
    }
447

    
448
    @Override
449
    public boolean isModified() {
450
        if( this.isReadOnly() ) {
451
            return false;
452
        }
453
        try {
454
            return (boolean) this.callUserFunction(USERCODE_FORM_ISMODIFIED, this, values);
455
        } catch (NoSuchMethodException ex) {
456
        } catch (Exception ex) {
457
            LOGGER.warn("Error calling user function form_IsModified.",ex);
458
        }
459
        Iterator it = this.getFieldsIterator();
460
        while (it.hasNext()) {
461
            JDynFormField jfield = (JDynFormField) it.next();
462
            if (jfield.isModified()) {
463
                return true;
464
            }
465
        }
466
        return false;
467
    }
468

    
469
    @Override
470
    public void fieldEnter(JDynFormField field) {
471
        message(field.getDefinition().getDescription());
472
        this.callUserEvent(USERCODE_FORM_ONFIELDENTER, this, field);
473
    }
474

    
475
    @Override
476
    public void fieldExit(JDynFormField field) {
477
        message();
478
        this.callUserEvent(USERCODE_FORM_ONFIELDEXIT, this, field);
479
    }
480

    
481
    @Override
482
    public void message(JDynFormField field, String message) {
483
        message(message);
484
    }
485

    
486
    @Override
487
    public void fieldChanged(JDynFormField field) {
488
        fireFieldChangeEvent(field);
489
        this.callUserEvent(USERCODE_FORM_ONFIELDCHANGED, this, field);
490
    }
491

    
492
    @Override
493
    public JDynFormField getField(String fieldName) {
494
        JDynFormField field = (JDynFormField) this.components.get(fieldName);
495
        return field;
496
    }
497

    
498
    public Iterator getFieldsIterator() {
499
        if (!this.isContentsInitialized()) {
500
            this.initComponents();
501
        }
502
        return this.components.values().iterator();
503
    }
504

    
505
    public Collection getShowFields() {
506
        return this.components.values();
507
    }
508

    
509
    @Override
510
    public void clear() {
511
        Iterator it = this.components.entrySet().iterator();
512
        while (it.hasNext()) {
513
            Map.Entry entry = (Map.Entry) it.next();
514
            ((JDynFormField) (entry.getValue())).clear();
515
        }
516
        this.callUserEvent(USERCODE_FORM_CLEAR, this);
517
    }
518

    
519
    @Override
520
    public void addActionToPopupMenu(DataType tipo, String name, Action action) {
521
        super.addActionToPopupMenu(tipo, name, action);
522
        if ( this.isContentsInitialized() ) {
523
            Iterator it = this.components.keySet().iterator();
524
            while (it.hasNext()) {
525
                String key = (String) it.next();
526
                Object obj = this.components.get(key);
527
                if (obj instanceof JDynFormField) {
528
                    JDynFormField field = (JDynFormField) obj;
529
                    if (tipo == field.getDefinition().getDataType()) {
530
                        if (field.asJComponent() instanceof SupportPopupMenu) {
531
                            field.addActionToPopupMenu(name, action);
532
                        }
533
                    }
534
                }
535
            }
536
        }
537
    }
538

    
539
    @Override
540
    public void addSeparatorToPopupMenu(DataType tipo) {
541
        super.addSeparatorToPopupMenu(tipo);
542
        if ( this.isContentsInitialized() ) {
543
            Iterator it = this.components.keySet().iterator();
544
            while (it.hasNext()) {
545
                String key = (String) it.next();
546
                Object obj = this.components.get(key);
547
                if (obj instanceof JDynFormField) {
548
                    JDynFormField field = (JDynFormField) obj;
549
                    if (tipo == field.getDefinition().getDataType()) {
550
                        if (field.asJComponent() instanceof SupportPopupMenu) {
551
                            ((SupportPopupMenu) field.asJComponent()).addSeparatorToPopupMenu();
552
                        }
553
                    }
554
                }
555
            }
556
        }
557
    }
558

    
559
    @Override
560
    public void setBorder(boolean border) {
561
        super.setBorder(border && this.getShowFields().size() >1);
562
    }
563

    
564
}