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

History | View | Annotate | Download (18.8 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 org.gvsig.tools.dynform.spi.dynform.JDynFormFactory;
59
import org.gvsig.tools.dynform.spi.dynformfield.JDynFormFieldFactory;
60
import org.gvsig.tools.dynform.spi.dynformfield.AbstractJDynFormField;
61

    
62
@SuppressWarnings("UseSpecificCatch")
63
public class DefaultJDynForm extends AbstractJDynForm implements JDynFormFieldListener {
64

    
65
    private Map components = null;
66
    private ComponentsFactory componentsFactory;
67

    
68
    public DefaultJDynForm(
69
            DynFormSPIManager manager, 
70
            JDynFormFactory factory,
71
            DynFormDefinition definition,
72
            DynFormContext context
73
        ) {
74
        super(manager, factory, definition, context);
75
        this.components = new HashMap();
76
        this.componentsFactory = manager.createDefaultComponentsFactory();
77
    }
78

    
79
    @Override
80
    protected JComponent getFieldsContainer() {
81

    
82
        try {
83
            JComponent component;
84
            switch (this.getLayoutMode()) {
85
                case USE_PLAIN:
86
                case USE_TREE:
87
                default:
88
                    component = getFieldsContainerPlain();
89
                    break;
90
                case USE_TABS:
91
                    component = getFieldsContainerUseTabs();
92
                    break;
93
                case USE_SEPARATORS:
94
                    component = getFieldsContainerUseSeparators();
95
                    break;
96
            }
97
            return component;
98
        } catch (ServiceException ex) {
99
            throw new RuntimeException(ex);
100
        }
101
    }
102

    
103
    private JComponent getFieldsContainerPlain() throws ServiceException {
104
        FormLayout layout = new FormLayout(
105
                "left:pref,  8px,  fill:80dlu:grow", "pref");
106

    
107
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
108
        builder.setDefaultRowSpec(new RowSpec(
109
                RowSpec.TOP,
110
                builder.getLayout().getRowSpec(1).getSize(),
111
                builder.getLayout().getRowSpec(1).getResizeWeight()));
112

    
113
        List fields = this.getDefinition().getDefinitions();
114
        Iterator it = fields.iterator();
115
        while (it.hasNext()) {
116
            DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
117
            if (fieldDefinition.isHidden()) {
118
                continue;
119
            }
120
            JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
121
                    this.getContext(),
122
                    fieldDefinition
123
            );
124
            JDynFormField jfield = factory.create(
125
                    getServiceManager(), 
126
                    this.componentsFactory,
127
                    fieldDefinition, 
128
                    null
129
            );
130
            if (jfield instanceof AbstractJDynFormField) {
131
                ((AbstractJDynFormField) jfield).setForm(this);
132
            }
133
            if (this.isReadOnly()) {
134
                jfield.setReadOnly(true);
135
            } else {
136
                jfield.setReadOnly(fieldDefinition.isReadOnly());
137
            }
138
            jfield.addListener(this);
139
            builder.append(jfield.getJLabel(), jfield.asJComponent());
140

    
141
            this.components.put(jfield.getName(), jfield);
142
        }
143
        return builder.getPanel();
144
    }
145

    
146
    private JComponent getFieldsContainerUseSeparators() throws ServiceException {
147
        List<String> groups = this.getDefinition().getGroups();
148

    
149
        FormLayout layout = new FormLayout(
150
                "left:pref,  8px,  fill:80dlu:grow", "pref");
151

    
152
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
153
        builder.setDefaultRowSpec(new RowSpec(
154
                RowSpec.TOP,
155
                builder.getLayout().getRowSpec(1).getSize(),
156
                builder.getLayout().getRowSpec(1).getResizeWeight()));
157

    
158
        for (String group : groups) {
159
            boolean firstfield = true;
160
            List fields = this.getDefinition().getDefinitions(group);
161
            Iterator it = fields.iterator();
162
            while (it.hasNext()) {
163
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
164
                if (fieldDefinition.isHidden()) {
165
                    continue;
166
                }
167
                JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
168
                        this.getContext(),
169
                        fieldDefinition
170
                );
171
                JDynFormField jfield = factory.create(
172
                        getServiceManager(), 
173
                        this.componentsFactory,
174
                        fieldDefinition, 
175
                        null
176
                );
177
                if (jfield instanceof AbstractJDynFormField) {
178
                    ((AbstractJDynFormField) jfield).setForm(this);
179
                }
180
                jfield.addListener(this);
181
                if (this.isReadOnly()) {
182
                    jfield.setReadOnly(this.isReadOnly());
183
                }
184

    
185
                List<Action> customActions = getCustomFields(fieldDefinition.getDataType());
186

    
187
                if (customActions != null && !customActions.isEmpty()) {
188
                    Iterator it2 = customActions.iterator();
189
                    while (it2.hasNext()) {
190
                        Object obj = it2.next();
191
                        if (obj != null) {
192
                            Action act = (Action) obj;
193
                            jfield.addActionToPopupMenu((String) act.getValue(Action.NAME), act);
194
                        } else {
195
                            jfield.addSeparatorToPopupMenu();
196
                        }
197
                    }
198
                }
199
                if( firstfield ) {
200
                    firstfield = false;
201
                    builder.appendSeparator(group);
202
                }
203
                builder.append(jfield.getJLabel(), jfield.asJComponent());
204

    
205
                this.components.put(jfield.getName(), jfield);
206
            }
207
        }
208
        return builder.getPanel();
209
    }
210

    
211
    private JComponent getFieldsContainerUseTabs() throws ServiceException {
212

    
213
        JTabbedPane tabbedPane = new JTabbedPane();
214
        tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
215
        if (this.getDefinition().getTags().has("TabPlacement")) {
216
            try {
217
                tabbedPane.setTabPlacement(this.getDefinition().getTags().getInt("TabPlacement"));
218
            } catch (Exception e) {
219
                // Ignorada
220
            }
221
        }
222
        List<String> groups = this.getDefinition().getGroups();
223

    
224
        for (String group : groups) {
225
            FormLayout layout = new FormLayout(
226
                    "left:pref,  8px,  fill:80dlu:grow", "pref");
227
            DefaultFormBuilder builder = new DefaultFormBuilder(layout);
228
            builder.defaultRowSpec(new RowSpec(
229
                    RowSpec.TOP,
230
                    builder.getLayout().getRowSpec(1).getSize(),
231
                    builder.getLayout().getRowSpec(1).getResizeWeight()));
232
            List fields = this.getDefinition().getDefinitions(group);
233
            boolean hasFields = false;
234
            Iterator it = fields.iterator();
235
            while (it.hasNext()) {
236
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
237
                if (fieldDefinition.isHidden()) {
238
                    continue;
239
                }
240
                JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
241
                        this.getContext(),
242
                        fieldDefinition
243
                );
244
                JDynFormField jfield = factory.create(
245
                        getServiceManager(), 
246
                        this.componentsFactory,
247
                        fieldDefinition, 
248
                        null
249
                );
250
                if (jfield instanceof AbstractJDynFormField) {
251
                    ((AbstractJDynFormField) jfield).setForm(this);
252
                }
253
                jfield.setReadOnly(this.isReadOnly());
254
                jfield.addListener(this);
255
                if (this.isReadOnly()) {
256
                    jfield.setReadOnly(this.isReadOnly());
257
                }
258
                hasFields = true;
259
                builder.append(jfield.getJLabel(), jfield.asJComponent());
260

    
261
                this.components.put(jfield.getName(), jfield);
262
            }
263
            if( hasFields ) {
264
                String tablabel = group;
265
                if (StringUtils.isEmpty(tablabel)) {
266
                    tablabel = ToolsLocator.getI18nManager().getTranslation("General");
267
                }
268
                tabbedPane.addTab(tablabel, builder.getPanel());
269
            }
270
        }
271

    
272
        try {
273
            String defaultGroupName = (String) this.getDefinition().getTags().get("defaultGroup", DataTypes.STRING);
274
            List<String> groupsNames = this.getDefinition().getGroups();
275
            int groupIndex = groupsNames.indexOf(defaultGroupName);
276
            if (groupIndex >= 0) {
277
                tabbedPane.setSelectedIndex(groupIndex);
278
            }
279
        } catch (Exception ex) {
280
            // Ignore errors and don't set a tab by default
281
        }
282

    
283
        return tabbedPane;
284
    }
285

    
286
    @Override
287
    public void setReadOnly(boolean readOnly) {
288
        if( this.isReadOnly() == readOnly ) {
289
            return;
290
        }
291
        super.setReadOnly(readOnly);
292
        if (this.isContentsInitialized()) {
293
            Iterator it = this.getFieldsIterator();
294
            while (it.hasNext()) {
295
                JDynFormField field = (JDynFormField) it.next();
296
                if( readOnly ) {
297
                    field.setReadOnly(true);
298
                } else if( field.getDefinition().isReadOnly() ) {
299
                    field.setReadOnly(true);
300
                } else {
301
                    field.setReadOnly(false);
302
                }
303
            }
304
        }
305
    }
306

    
307
    @Override
308
    public void setValues(DynObject values) {
309
        /*
310
         * TODO: Probablemente fuese mas acertado recorrer los controles de
311
         * components y a partir de ellos acceder a los valores del DynObject
312
         * recibido. Eso permitiria trabajar mejor con herencia de DynObject.
313
         * Habria que hacer lo mismo con el getValues.
314
         */
315
        if (!this.isContentsInitialized()) {
316
            this.values = values;
317
            return;
318
        }
319
        DynClass def = values.getDynClass();
320
        DynField[] fields = def.getDynFields();
321
        for (int i = 0; i < fields.length; i++) {
322
            String name = fields[i].getName();
323
            if (name == null || name.isEmpty()) {
324
                LOGGER.warn("Field name " + i + " of '" + def.getFullName() + "' is null or empty ");
325
                continue;
326
            }
327
            JDynFormField jfield = (JDynFormField) this.getField(name);
328
            if (jfield == null) {
329
                LOGGER.warn("Can't retrieve form field asociated to the field '" + name + "' of class '" + def.getFullName() + "'.");
330
                continue;
331
            }
332
            if (values.getDynValue(name) == null) {
333
                if (fields[i].getDataType().getType() == DataTypes.LIST) {
334
                    try {
335
                        if (((DynField_v2) fields[i]).getDynClassOfItems() != null) {
336
                            values.setDynValue(name, new ArrayList<>());
337
                        }
338
                    } catch (Exception e) {
339
                        LOGGER.warn("Problems initializing the DynObject List", e);
340
                    }
341
                }
342
            }
343
            jfield.setValue(values.getDynValue(name));
344
        }
345
    }
346

    
347
    @Override
348
    public void getValues(DynObject values) {
349
        if (values == null) {
350
            return;
351
        }
352
        DynField[] fields = values.getDynClass().getDynFields();
353
        for (DynField field : fields) {
354
            String name = field.getName();
355
            JDynFormField jfield = (JDynFormField) this.getField(name);
356
            if (jfield != null && !jfield.isReadOnly()) {
357
                try {
358
                    jfield.fetch(values);
359
                } catch (Exception ex) {
360
                    LOGGER.warn("Can't get value of field '" + name + "'.", ex);
361
                }
362
            }
363
        }
364
    }
365

    
366
    @Override
367
    public boolean hasValidValues() {
368
        Iterator it = this.getFieldsIterator();
369
        while (it.hasNext()) {
370
            JDynFormField jfield = (JDynFormField) it.next();
371
            if (!jfield.hasValidValue()) {
372
                return false;
373
            }
374
        }
375
        return true;
376
    }
377

    
378
    @Override
379
    public boolean hasValidValues(List<String> fieldsName) {
380
        if (fieldsName == null) {
381
            fieldsName = new ArrayList<>();
382
        }
383
        Iterator it = this.getFieldsIterator();
384
        while (it.hasNext()) {
385
            JDynFormField jfield = (JDynFormField) it.next();
386
            if (!jfield.hasValidValue()) {
387
                fieldsName.add(jfield.getName());
388
            }
389
        }
390
        return fieldsName.isEmpty();
391
    }
392

    
393
    @Override
394
    public Object getValue(String fieldName) {
395
        JDynFormField field = (JDynFormField) this.getField(fieldName);
396
        return field.getValue();
397
    }
398

    
399
    @Override
400
    public void setValue(String fieldName, Object value) {
401
        JDynFormField field = (JDynFormField) this.getField(fieldName);
402
        try {
403
            value = field.getDefinition().getDataType().coerce(value);
404
        } catch (CoercionException e) {
405
            String msg = "Invalid value '" + ((value == null) ? "(null)" : value.toString()) + "' for field '" + fieldName + "'.";
406
            LOGGER.warn(msg, e);
407
            throw new RuntimeException(msg, e);
408
        }
409
        field.setValue(value);
410
    }
411

    
412
    @Override
413
    public boolean isModified() {
414
        if( this.isReadOnly() ) {
415
            return false;
416
        }
417
        Iterator it = this.getFieldsIterator();
418
        while (it.hasNext()) {
419
            JDynFormField jfield = (JDynFormField) it.next();
420
            if (jfield.isModified()) {
421
                return true;
422
            }
423
        }
424
        return false;
425
    }
426

    
427
    @Override
428
    public void fieldEnter(JDynFormField field) {
429
        message(field.getDefinition().getDescription());
430
    }
431

    
432
    @Override
433
    public void fieldExit(JDynFormField field) {
434
        message();
435
    }
436

    
437
    @Override
438
    public void message(JDynFormField field, String message) {
439
        message(message);
440
    }
441

    
442
    @Override
443
    public void fieldChanged(JDynFormField field) {
444
        fireFieldChangeEvent(field);
445
    }
446

    
447
    @Override
448
    public JDynFormField getField(String fieldName) {
449
        JDynFormField field = (JDynFormField) this.components.get(fieldName);
450
        return field;
451
    }
452

    
453
    public Iterator getFieldsIterator() {
454
        if (!this.isContentsInitialized()) {
455
            this.initComponents();
456
        }
457
        return this.components.values().iterator();
458
    }
459

    
460
    public Collection getShowFields() {
461
        return this.components.values();
462
    }
463

    
464
    @Override
465
    public void clear() {
466
        Iterator it = this.components.entrySet().iterator();
467
        while (it.hasNext()) {
468
            Map.Entry entry = (Map.Entry) it.next();
469
            ((JDynFormField) (entry.getValue())).clear();
470
        }
471
    }
472

    
473
    @Override
474
    public void addActionToPopupMenu(DataType tipo, String name, Action action) {
475
        super.addActionToPopupMenu(tipo, name, action);
476
        if ( this.isContentsInitialized() ) {
477
            Iterator it = this.components.keySet().iterator();
478
            while (it.hasNext()) {
479
                String key = (String) it.next();
480
                Object obj = this.components.get(key);
481
                if (obj instanceof JDynFormField) {
482
                    JDynFormField field = (JDynFormField) obj;
483
                    if (tipo == field.getDefinition().getDataType()) {
484
                        if (field.asJComponent() instanceof SupportPopupMenu) {
485
                            field.addActionToPopupMenu(name, action);
486
                        }
487
                    }
488
                }
489
            }
490
        }
491
    }
492

    
493
    @Override
494
    public void addSeparatorToPopupMenu(DataType tipo) {
495
        super.addSeparatorToPopupMenu(tipo);
496
        if ( this.isContentsInitialized() ) {
497
            Iterator it = this.components.keySet().iterator();
498
            while (it.hasNext()) {
499
                String key = (String) it.next();
500
                Object obj = this.components.get(key);
501
                if (obj instanceof JDynFormField) {
502
                    JDynFormField field = (JDynFormField) obj;
503
                    if (tipo == field.getDefinition().getDataType()) {
504
                        if (field.asJComponent() instanceof SupportPopupMenu) {
505
                            ((SupportPopupMenu) field.asJComponent()).addSeparatorToPopupMenu();
506
                        }
507
                    }
508
                }
509
            }
510
        }
511
    }
512

    
513
    @Override
514
    public void setBorder(boolean border) {
515
        super.setBorder(border && this.getShowFields().size() >1);
516
    }
517

    
518
}