Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.dynform / org.gvsig.tools.dynform.spi / src / main / java / org / gvsig / tools / dynform / spi / dynformfield / AbstractJDynFormField.java @ 2487

History | View | Annotate | Download (19.5 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.spi.dynformfield;
24

    
25
import java.awt.BorderLayout;
26
import java.awt.Color;
27
import java.awt.event.FocusEvent;
28
import java.awt.event.FocusListener;
29
import java.util.ArrayList;
30
import java.util.HashSet;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Objects;
34
import java.util.Set;
35

    
36
import javax.swing.Action;
37
import javax.swing.JComboBox;
38
import javax.swing.JComponent;
39
import javax.swing.JLabel;
40
import javax.swing.JPanel;
41
import javax.swing.JScrollPane;
42
import javax.swing.JViewport;
43
import javax.swing.text.JTextComponent;
44
import org.apache.commons.lang3.StringUtils;
45
import org.gvsig.tools.ToolsLocator;
46
import org.gvsig.tools.dataTypes.CoercionException;
47
import org.gvsig.tools.dataTypes.DataTypes;
48

    
49
import org.gvsig.tools.dynform.DynFormFieldDefinition;
50
import org.gvsig.tools.dynform.JDynForm;
51
import org.gvsig.tools.dynform.JDynFormField;
52
import org.gvsig.tools.dynform.spi.DynFormSPIManager;
53
import org.gvsig.tools.dynform.spi.DynFormSPIManager.ComponentsFactory;
54
import org.gvsig.tools.dynobject.DynClass;
55
import org.gvsig.tools.dynobject.DynField;
56
import org.gvsig.tools.dynobject.DynField_v2;
57
import org.gvsig.tools.dynobject.DynObject;
58
import org.gvsig.tools.dynobject.Tags;
59
import org.slf4j.Logger;
60
import org.slf4j.LoggerFactory;
61

    
62
@SuppressWarnings({"rawtypes", "unchecked"})
63
public abstract class AbstractJDynFormField implements JDynFormField, FocusListener {
64

    
65
    protected static final Logger LOGGER = LoggerFactory
66
            .getLogger(AbstractJDynFormField.class);
67

    
68
    private final DynFormSPIManager manager;
69
    private final JDynFormFieldFactory factory;
70
    private final DynFormFieldDefinition definition;
71
    private final ComponentsFactory componentsFactory;
72

    
73
    private JDynForm form;
74
    
75
    protected JLabel jlabel = null;
76
    private JPanel jlabelpanel = null;
77
    private Set listeners = null;
78
    private JProblemIndicator problemIndicator = null;
79

    
80
    protected JComponent contents = null;
81

    
82
    protected boolean readOnly = false;
83
    private final List customActions;
84
    protected boolean emptyToNull = false;
85

    
86
    public AbstractJDynFormField(
87
            DynFormSPIManager serviceManager, 
88
            ComponentsFactory componentsFactory,
89
            JDynFormFieldFactory factory, 
90
            DynFormFieldDefinition definition,
91
            Object value
92
        ) {
93
        this.manager = serviceManager;
94
        this.factory = factory;
95
        this.definition = definition;
96
        this.componentsFactory = componentsFactory;
97
        this.listeners = new HashSet();
98
        this.problemIndicator = this.manager.createProblemIndicator(this);
99
        this.customActions = new ArrayList<>();
100
        if(this.definition != null){
101
                this.readOnly = this.definition.isReadOnly();
102
                this.loadDefaultValuesFromTags(definition.getTags());
103
        }
104
    }
105

    
106
    public ComponentsFactory getComponentsFactory() {
107
        return this.componentsFactory;
108
    }
109
    
110
    public void loadDefaultValuesFromTags(Tags tags) {
111
        try {
112
            this.readOnly = tags.getBoolean(DynFormSPIManager.TAG_DYNFORM_READONLY);
113
        } catch (CoercionException ex) {
114
        }
115
        try {
116
            this.emptyToNull = tags.getBoolean(DynFormSPIManager.TAG_DYNFORM_TRANSLATE_EMPTY_TO_NULL);
117
        } catch (CoercionException ex) {
118
        }
119
    }
120

    
121
    public abstract void initComponent();
122

    
123
    public abstract Object getAssignedValue();
124

    
125
//    public Object getParameterValue() {
126
//        return this.parameters.getDynValue(DynFormSPIManager.FIELD_VALUE);
127
//    }
128
//
129
    @Override
130
    public JComponent asJComponent() {
131
        if (this.contents == null) {
132
            try {
133
                this.initComponent();
134
            } catch(Throwable th) {
135
                this.contents = new JLabel("##ERROR##");
136
                this.problemIndicator().set("Can't create component");
137
            }
138
            if (!this.customActions.isEmpty()) {
139
                addPopupComponents();
140
            }
141
            if (this.readOnly) {
142
                this.setReadOnly(readOnly);
143
            }
144
        }
145
        return this.contents;
146
    }
147

    
148
    @Override
149
    public String getName() {
150
        return this.definition.getName();
151
    }
152

    
153
    @Override
154
    public String getLabel() {
155
        if (definition.getLabel() != null) {
156
            String label = definition.getLabel();
157
            label = ToolsLocator.getI18nManager().getTranslation(label);
158
            return label;
159
        } else {
160
            return this.getName();
161
        }
162
    }
163

    
164
    @Override
165
    public String getSeparatorTitleToUseBefore() {
166
        String separatorTitle = this.getTagValueAsString(
167
                DynFormSPIManager.TAG_DYNFORM_SEPARATOR, 
168
                null
169
        );
170
        return separatorTitle;
171
    }
172
    
173
    @Override
174
    public boolean useEmptyLabel() {
175
        boolean useEmpty = getTagValueAsBoolean(
176
                DynFormSPIManager.TAG_DYNFORM_LABEL_EMPTY, 
177
                false
178
        );
179
        return useEmpty;
180
    }
181
    
182
    @Override
183
    public JComponent getJLabel() {
184
        if (this.jlabel == null) {
185
            this.jlabel = this.getComponentsFactory().getJLabel(definition, null);
186
            if( this.jlabel==null ) {
187
                this.jlabel = new JLabel();
188
            }
189
            if (!this.useEmptyLabel() ) {
190
                this.jlabel.setText(this.getLabel());
191
            }
192
            this.jlabel.setLabelFor(this.contents);
193
            if (this.getDefinition().isMandatory()) {
194
                this.jlabel.setForeground(Color.red.darker());
195
            }
196
            this.jlabelpanel = new JPanel();
197
            this.jlabelpanel.setLayout(new BorderLayout());
198
            this.jlabelpanel.add(jlabel, BorderLayout.CENTER);
199
            this.jlabelpanel.add(problemIndicator.asJComponent(), BorderLayout.LINE_END);
200
        }
201
        return this.jlabelpanel;
202
    }
203

    
204
    @Override
205
    public DynFormFieldDefinition getDefinition() {
206
        return this.definition;
207
    }
208
    
209
    public DynFormSPIManager getServiceManager() {
210
        return this.manager;
211
    }
212

    
213
    @Override
214
    public void addListener(JDynFormFieldListener listener) {
215
        this.listeners.add(listener);
216
    }
217

    
218
    @Override
219
    public void removeListener(JDynFormFieldListener listener) {
220
        this.listeners.remove(listener);
221
    }
222

    
223
    protected void fireFieldChangedEvent() {
224
        if( this.isReadOnly() ) {
225
            return;
226
        }
227
        Iterator it = this.listeners.iterator();
228
        while (it.hasNext()) {
229
            JDynFormFieldListener listener = (JDynFormFieldListener) it.next();
230
            try {
231
                listener.fieldChanged(this);
232
            } catch (Exception ex) {
233
                LOGGER.info("Error calling listener " + listener.toString()
234
                        + "(" + listener.getClass().getName() + ") from "
235
                        + this.toString() + "(" + this.getClass().getName()
236
                        + ").", ex);
237
            }
238
        }
239
    }
240

    
241
    protected void fireFieldEnterEvent() {
242
        Iterator it = this.listeners.iterator();
243
        while (it.hasNext()) {
244
            JDynFormFieldListener listener = (JDynFormFieldListener) it.next();
245
            try {
246
                listener.fieldEnter(this);
247
            } catch (Exception ex) {
248
                LOGGER.info("Error calling listener " + listener.toString()
249
                        + "(" + listener.getClass().getName() + ") from "
250
                        + this.toString() + "(" + this.getClass().getName()
251
                        + ").", ex);
252
            }
253
        }
254
    }
255

    
256
    protected void fireFieldExitEvent() {
257
        Iterator it = this.listeners.iterator();
258
        while (it.hasNext()) {
259
            JDynFormFieldListener listener = (JDynFormFieldListener) it.next();
260
            try {
261
                listener.fieldExit(this);
262
            } catch (Exception ex) {
263
                LOGGER.info("Error calling listener " + listener.toString()
264
                        + "(" + listener.getClass().getName() + ") from "
265
                        + this.toString() + "(" + this.getClass().getName()
266
                        + ").", ex);
267
            }
268
        }
269
    }
270

    
271
    @Override
272
    public void fireMessageEvent(String message) {
273
        Iterator it = this.listeners.iterator();
274
        while (it.hasNext()) {
275
            JDynFormFieldListener listener = (JDynFormFieldListener) it.next();
276
            try {
277
                listener.message(this, message);
278
            } catch (Exception ex) {
279
                LOGGER.info("Error calling listener " + listener.toString()
280
                        + "(" + listener.getClass().getName() + ") from "
281
                        + this.toString() + "(" + this.getClass().getName()
282
                        + ").", ex);
283
            }
284
        }
285
    }
286

    
287
    @Override
288
    public boolean isReadOnly() {
289
        return this.readOnly;
290
    }
291
    
292
    protected boolean isForcedReadOnly() {
293
        return this.getTagValueAsBoolean(DynFormSPIManager.TAG_DYNFORM_READONLY, false);
294
    }
295

    
296
    @Override
297
    public void setReadOnly(boolean readonly) {
298
        // FIXME: Implememtacion por defecto, sobreescribirla en las subclases
299
        // segun convenga para cada componente.
300
        if( !readonly && this.isForcedReadOnly() ) {
301
            readonly = true;
302
        }
303
        this.readOnly = readonly;
304
        if (jlabel != null) {
305
            this.jlabel.setEnabled(!readonly);
306
        }
307
        if (this.contents != null) {
308
            if (this.contents instanceof JTextComponent) {
309
                JTextComponent x = (JTextComponent) this.contents;
310
                x.setEditable(!readonly);
311

    
312
            } else if (this.contents instanceof JComboBox ) {
313
                JComboBox x = (JComboBox) this.contents;
314
                x.setEnabled(!readonly);
315
                
316
            } else if (this.contents instanceof JScrollPane) {
317
                try {
318
                    JViewport port = ((JScrollPane) this.contents).getViewport();
319
                    JTextComponent x = (JTextComponent) port.getView();
320
                    x.setEditable(!readonly);
321
                } catch (Exception ex) {
322
                    this.contents.setEnabled(!readOnly);
323
                }
324
            } else {
325
                this.contents.setEnabled(!readOnly);
326
            }
327
        }
328
    }
329

    
330
    public JProblemIndicator problemIndicator() {
331
        return this.problemIndicator;
332
    }
333

    
334
    public class IllegalFieldValue extends RuntimeException {
335

    
336
        /**
337
         *
338
         */
339
        private static final long serialVersionUID = -4409236610055983438L;
340

    
341
        public IllegalFieldValue(JDynFormField field, String message) {
342
            super("The value of field '" + field.getLabel() + "' is not valid. " + message);
343
        }
344
    }
345

    
346
    @Override
347
    public String toString() {
348
        return super.toString() + "{" + this.getName() + "}";
349
    }
350

    
351
    @Override
352
    public boolean isModified() {
353
        boolean modified = false;
354
        try {
355
            if (!this.isReadOnly()) {
356
                Object value = this.getValue();
357
                if (value == null) {
358
                    Object x = this.getAssignedValue();
359
                    if (StringUtils.isNotBlank(Objects.toString(x,null))) {
360
                        modified = true;
361
                    }
362
                } else {
363
                    Object x = this.getAssignedValue();
364
                    if (x instanceof CharSequence){
365
                        if (!StringUtils.equals((CharSequence) x, value.toString())){
366
                            modified = true;
367
                        }
368
                    }else if (!value.equals(this.getAssignedValue())) {
369
                        modified = true;
370
                    }
371
                }
372
            }
373
        } catch (IllegalFieldValue ex) {
374
            // Si es incorrecto el valor del campo decimos a capom que esta modificado.
375
            modified = true;
376
        }
377
        return modified;
378
    }
379

    
380
    private void addPopupComponents() {
381
        Iterator it = this.customActions.iterator();
382
        while (it.hasNext()) {
383
            Object obj = it.next();
384
            if (obj != null) {
385
                Action act = (Action) obj;
386
                if (contents instanceof SupportPopupMenu) {
387
                    DynFormFieldAction sact = new DynFormFieldAction(this, act);
388
                    ((SupportPopupMenu) this.contents).addActionToPopupMenu(
389
                            sact.getName(),
390
                            sact);
391
                }
392
            } else {
393
                if (contents instanceof SupportPopupMenu) {
394
                    ((SupportPopupMenu) this.contents).addSeparatorToPopupMenu();
395
                }
396
            }
397

    
398
        }
399
    }
400

    
401
    @Override
402
    public void addActionToPopupMenu(String name, Action action) {
403
        if (contents != null) {
404
            if (contents instanceof SupportPopupMenu) {
405
                DynFormFieldAction sact = new DynFormFieldAction(this, action);
406
                ((SupportPopupMenu) this.contents).addActionToPopupMenu(
407
                        sact.getName(),
408
                        sact);
409
            }
410
        } else {
411
            this.customActions.add(action);
412
        }
413
    }
414

    
415
    @Override
416
    public void addSeparatorToPopupMenu() {
417
        if (contents != null) {
418
            if (contents instanceof SupportPopupMenu) {
419
                ((SupportPopupMenu) this.contents).addSeparatorToPopupMenu();
420
            }
421
        } else {
422
            this.customActions.add(null);
423
        }
424
    }
425

    
426
    public void setTranslateEmptyToNull(boolean emptyToNull) {
427
        this.emptyToNull = emptyToNull;
428
    }
429

    
430
    public boolean translateEmptyToNull() {
431
        return this.emptyToNull;
432
    }
433

    
434
    @SuppressWarnings("UnnecessaryReturnStatement")
435
    @Override
436
    public void clear() {
437
        if (this.contents == null) {
438
            return;
439
        }
440
        Object value = this.getDefinition().getDefaultValue();
441
        this.setValue(value);
442
//        if (this.contents instanceof JTextField) {
443
//            if (value != null) {
444
//                value = value.toString();
445
//            } else {
446
//                value = "";
447
//            }
448
//            ((JTextField) this.contents).setText((String) value);
449
//            return;
450
//        }
451
//        if (this.contents instanceof JSpinner) {
452
//            if (value==null) {
453
//                ((JSpinner) this.contents).setValue(0);
454
//                return;
455
//            }
456
//            ((JSpinner) this.contents).setValue(value);
457
//            return;
458
//        }
459
//        if (this.contents instanceof JList) {
460
//            ((JList) this.contents).setSelectedIndex(-1);
461
//            return;
462
//        }
463
//        if (this.contents instanceof JComboBox) {
464
//            ((JComboBox) this.contents).setSelectedIndex(-1);
465
//            return;
466
//        }
467
    }
468

    
469
    public void setForm(JDynForm form) {
470
        this.form = form;
471
    }
472

    
473
    @Override
474
    public JDynForm getForm() {
475
        return this.form;
476
    }
477

    
478
    @Override
479
    public void fetch(DynObject container) {
480
        if( this.isReadOnly() ) {
481
            return;
482
        }
483
        Object value = this.getValue();
484
        DynClass dynclass = container.getDynClass();
485
        if( dynclass!=null ) {
486
            DynField dynfield = dynclass.getDynField(this.getName());
487
            if( dynfield!=null && dynfield.isReadOnly() ) {
488
                return;
489
            }
490
        }
491
        container.setDynValue(this.getName(), value);
492
    }
493

    
494
    protected int getTagValueAsInt(String tagname, int defaultVaue) {
495
        return getTagValueAsInt(tagname, null, defaultVaue);
496
    }
497

    
498
    protected int getTagValueAsInt(String tagname1, String tagname2, int defaultVaue) {
499
        DynField_v2 fielddef = (DynField_v2) this.getDefinition();
500
        String tagname;
501
        if (fielddef.getTags().has(tagname1)) {
502
            tagname = tagname1;
503
        } else if (fielddef.getTags().has(tagname2)) {
504
            tagname = tagname2;
505
        } else {
506
            return defaultVaue;
507
        }
508
        try {
509
            int value = fielddef.getTags().getInt(tagname);
510
            return value;
511
        } catch (CoercionException ex) {
512
            LOGGER.warn("Can't parse tag '" + tagname + "' as int for field '" + fielddef.getName() + "'.", ex);
513
        }
514
        return defaultVaue;
515
    }
516

    
517
    protected boolean getTagValueAsBoolean(String tagname, boolean defaultVaue) {
518
        return getTagValueAsBoolean(tagname, null, defaultVaue);
519
    }
520

    
521
    protected boolean getTagValueAsBoolean(String tagname1, String tagname2, boolean defaultVaue) {
522
        DynField_v2 fielddef = (DynField_v2) this.getDefinition();
523
        String tagname;
524
        if (fielddef.getTags().has(tagname1)) {
525
            tagname = tagname1;
526
        } else if (fielddef.getTags().has(tagname2)) {
527
            tagname = tagname2;
528
        } else {
529
            return defaultVaue;
530
        }
531
        try {
532
            boolean value = fielddef.getTags().getBoolean(tagname);
533
            return value;
534
        } catch (CoercionException ex) {
535
            LOGGER.warn("Can't parse tag '" + tagname + "' as boolean for field '" + fielddef.getName() + "'.", ex);
536
        }
537
        return defaultVaue;
538
    }
539

    
540
    protected String getTagValueAsString(String tagname, String defaultVaue) {
541
        return getTagValueAsString(tagname, null, defaultVaue);
542
    }
543

    
544
    protected String getTagValueAsString(String tagname1, String tagname2, String defaultVaue) {
545
        DynField_v2 fielddef = (DynField_v2) this.getDefinition();
546
        String tagname;
547
        if (fielddef.getTags().has(tagname1)) {
548
            tagname = tagname1;
549
        } else if (fielddef.getTags().has(tagname2)) {
550
            tagname = tagname2;
551
        } else {
552
            return defaultVaue;
553
        }
554
        try {
555
            String value = (String) fielddef.getTags().get(tagname, DataTypes.STRING);
556
            return value;
557
        } catch (CoercionException ex) {
558
            LOGGER.warn("Can't parse tag '" + tagname + "' as string for field '" + fielddef.getName() + "'.", ex);
559
        }
560
        return defaultVaue;
561
    }
562

    
563
    @Override
564
    public double getResizeWeight() {
565
        Tags tags = this.getDefinition().getTags();
566
        int resizeWeight = tags.getInt(DynFormSPIManager.TAG_DYNFORM_RESIZEWEIGHT, 0);
567
        if( resizeWeight<1 ) {
568
            return 0;
569
        }
570
        if( resizeWeight>100 ) {
571
            return 1;
572
        }
573
        return resizeWeight / 100.0;
574
    }
575

    
576
    @Override
577
    public void focusGained(FocusEvent arg0) {
578
        fireFieldEnterEvent();
579
        this.problemIndicator().restore();
580
    }
581

    
582
    @Override
583
    public void focusLost(FocusEvent arg0) {
584
        if (this.hasValidValue()) {
585
            this.problemIndicator().clear();
586
        } else {
587
            try {
588
                Object value = this.getValue();
589
            } catch (Exception e) {
590
                this.problemIndicator().set(e.getLocalizedMessage());
591
            }
592
        }
593
        fireFieldExitEvent();
594
    }
595
    
596
}