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

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

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

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

    
51
import org.gvsig.tools.dynform.DynFormFieldDefinition;
52
import org.gvsig.tools.dynform.JDynForm;
53
import org.gvsig.tools.dynform.JDynFormField;
54
import org.gvsig.tools.dynform.spi.DynFormSPIManager;
55
import org.gvsig.tools.dynform.spi.DynFormSPIManager.ComponentsFactory;
56
import org.gvsig.tools.dynobject.DynClass;
57
import org.gvsig.tools.dynobject.DynField;
58
import org.gvsig.tools.dynobject.DynField_v2;
59
import org.gvsig.tools.dynobject.DynObject;
60
import org.gvsig.tools.dynobject.Tags;
61
import org.gvsig.tools.swing.api.ToolsSwingLocator;
62
import org.gvsig.tools.swing.icontheme.IconTheme;
63
import org.gvsig.tools.swing.icontheme.IconThemeManager;
64
import org.slf4j.Logger;
65
import org.slf4j.LoggerFactory;
66

    
67
@SuppressWarnings({"rawtypes", "unchecked"})
68
public abstract class AbstractJDynFormField implements JDynFormField, FocusListener {
69

    
70
    protected static final Logger LOGGER = LoggerFactory
71
            .getLogger(AbstractJDynFormField.class);
72

    
73
    private final DynFormSPIManager manager;
74
    private final JDynFormFieldFactory factory;
75
    private final DynFormFieldDefinition definition;
76
    private final ComponentsFactory componentsFactory;
77

    
78
    private JDynForm form;
79
    
80
    protected JLabel jlabel = null;
81
    private JPanel jlabelpanel = null;
82
    private Set listeners = null;
83
    private JProblemIndicator problemIndicator = null;
84

    
85
    protected JComponent contents = null;
86

    
87
    protected boolean readOnly = false;
88
    private final List customActions;
89
    protected boolean emptyToNull = false;
90

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

    
111
    public ComponentsFactory getComponentsFactory() {
112
        return this.componentsFactory;
113
    }
114
    
115
    public void loadDefaultValuesFromTags(Tags tags) {
116
        try {
117
            this.readOnly = tags.getBoolean(DynFormSPIManager.TAG_DYNFORM_READONLY);
118
        } catch (CoercionException ex) {
119
        }
120
        try {
121
            this.emptyToNull = tags.getBoolean(DynFormSPIManager.TAG_DYNFORM_TRANSLATE_EMPTY_TO_NULL);
122
        } catch (CoercionException ex) {
123
        }
124
    }
125

    
126
    public abstract void initComponent();
127

    
128
    public abstract Object getAssignedValue();
129

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

    
153
    @Override
154
    public String getName() {
155
        return this.definition.getName();
156
    }
157

    
158
    @Override
159
    public String getLabel() {
160
        if (definition.getLabel() != null) {
161
            String label = definition.getLabel();
162
            label = ToolsLocator.getI18nManager().getTranslation(label);
163
            return label;
164
        } else {
165
            return this.getName();
166
        }
167
    }
168

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

    
209
    @Override
210
    public DynFormFieldDefinition getDefinition() {
211
        return this.definition;
212
    }
213
    
214
    public DynFormSPIManager getServiceManager() {
215
        return this.manager;
216
    }
217

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

    
223
    @Override
224
    public void removeListener(JDynFormFieldListener listener) {
225
        this.listeners.remove(listener);
226
    }
227

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

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

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

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

    
292
    @Override
293
    public boolean isReadOnly() {
294
        return this.readOnly;
295
    }
296
    
297
    protected boolean isForcedReadOnly() {
298
        return this.getTagValueAsBoolean(DynFormSPIManager.TAG_DYNFORM_READONLY, false);
299
    }
300

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

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

    
335
    public JProblemIndicator problemIndicator() {
336
        return this.problemIndicator;
337
    }
338

    
339
    public class IllegalFieldValue extends RuntimeException {
340

    
341
        /**
342
         *
343
         */
344
        private static final long serialVersionUID = -4409236610055983438L;
345

    
346
        public IllegalFieldValue(JDynFormField field, String message) {
347
            super("The value of field '" + field.getLabel() + "' is not valid. " + message);
348
        }
349
    }
350

    
351
    @Override
352
    public String toString() {
353
        return super.toString() + "{" + this.getName() + "}";
354
    }
355

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

    
389
    private void addPopupComponents() {
390
        Iterator it = this.customActions.iterator();
391
        while (it.hasNext()) {
392
            Object obj = it.next();
393
            if (obj != null) {
394
                Action act = (Action) obj;
395
                if (contents instanceof SupportPopupMenu) {
396
                    DynFormFieldAction sact = new DynFormFieldAction(this, act);
397
                    ((SupportPopupMenu) this.contents).addActionToPopupMenu(
398
                            sact.getName(),
399
                            sact);
400
                }
401
            } else {
402
                if (contents instanceof SupportPopupMenu) {
403
                    ((SupportPopupMenu) this.contents).addSeparatorToPopupMenu();
404
                }
405
            }
406

    
407
        }
408
    }
409

    
410
    @Override
411
    public void addActionToPopupMenu(String name, Action action) {
412
        if (contents != null) {
413
            if (contents instanceof SupportPopupMenu) {
414
                DynFormFieldAction sact = new DynFormFieldAction(this, action);
415
                ((SupportPopupMenu) this.contents).addActionToPopupMenu(
416
                        sact.getName(),
417
                        sact);
418
            }
419
        } else {
420
            this.customActions.add(action);
421
        }
422
    }
423

    
424
    @Override
425
    public void addSeparatorToPopupMenu() {
426
        if (contents != null) {
427
            if (contents instanceof SupportPopupMenu) {
428
                ((SupportPopupMenu) this.contents).addSeparatorToPopupMenu();
429
            }
430
        } else {
431
            this.customActions.add(null);
432
        }
433
    }
434

    
435
    public void setTranslateEmptyToNull(boolean emptyToNull) {
436
        this.emptyToNull = emptyToNull;
437
    }
438

    
439
    public boolean translateEmptyToNull() {
440
        return this.emptyToNull;
441
    }
442

    
443
    @SuppressWarnings("UnnecessaryReturnStatement")
444
    @Override
445
    public void clear() {
446
        if (this.contents == null) {
447
            return;
448
        }
449
        Object value = this.getDefinition().getDefaultValue();
450
        this.setValue(value);
451
//        if (this.contents instanceof JTextField) {
452
//            if (value != null) {
453
//                value = value.toString();
454
//            } else {
455
//                value = "";
456
//            }
457
//            ((JTextField) this.contents).setText((String) value);
458
//            return;
459
//        }
460
//        if (this.contents instanceof JSpinner) {
461
//            if (value==null) {
462
//                ((JSpinner) this.contents).setValue(0);
463
//                return;
464
//            }
465
//            ((JSpinner) this.contents).setValue(value);
466
//            return;
467
//        }
468
//        if (this.contents instanceof JList) {
469
//            ((JList) this.contents).setSelectedIndex(-1);
470
//            return;
471
//        }
472
//        if (this.contents instanceof JComboBox) {
473
//            ((JComboBox) this.contents).setSelectedIndex(-1);
474
//            return;
475
//        }
476
    }
477

    
478
    public void setForm(JDynForm form) {
479
        this.form = form;
480
    }
481

    
482
    @Override
483
    public JDynForm getForm() {
484
        return this.form;
485
    }
486

    
487
    @Override
488
    public void fetch(DynObject container) {
489
//        if( this.isReadOnly() ) {
490
//            return;
491
//        }
492
        Object value = this.getValue();
493
        DynClass dynclass = container.getDynClass();
494
        if( dynclass!=null ) {
495
            DynField dynfield = dynclass.getDynField(this.getName());
496
            if( dynfield!=null && dynfield.isReadOnly() ) {
497
                return;
498
            }
499
        }
500
        container.setDynValue(this.getName(), value);
501
    }
502

    
503
    protected int getTagValueAsInt(String tagname, int defaultVaue) {
504
        return getTagValueAsInt(tagname, null, defaultVaue);
505
    }
506

    
507
    protected int getTagValueAsInt(String tagname1, String tagname2, int defaultVaue) {
508
        DynField_v2 fielddef = (DynField_v2) this.getDefinition();
509
        String tagname;
510
        if (fielddef.getTags().has(tagname1)) {
511
            tagname = tagname1;
512
        } else if (fielddef.getTags().has(tagname2)) {
513
            tagname = tagname2;
514
        } else {
515
            return defaultVaue;
516
        }
517
        try {
518
            int value = fielddef.getTags().getInt(tagname);
519
            return value;
520
        } catch (CoercionException ex) {
521
            LOGGER.warn("Can't parse tag '" + tagname + "' as int for field '" + fielddef.getName() + "'.", ex);
522
        }
523
        return defaultVaue;
524
    }
525

    
526
    protected boolean getTagValueAsBoolean(String tagname, boolean defaultVaue) {
527
        return getTagValueAsBoolean(tagname, null, defaultVaue);
528
    }
529

    
530
    protected boolean getTagValueAsBoolean(String tagname1, String tagname2, boolean defaultVaue) {
531
        DynField_v2 fielddef = (DynField_v2) this.getDefinition();
532
        String tagname;
533
        if (fielddef.getTags().has(tagname1)) {
534
            tagname = tagname1;
535
        } else if (fielddef.getTags().has(tagname2)) {
536
            tagname = tagname2;
537
        } else {
538
            return defaultVaue;
539
        }
540
        try {
541
            boolean value = fielddef.getTags().getBoolean(tagname);
542
            return value;
543
        } catch (CoercionException ex) {
544
            LOGGER.warn("Can't parse tag '" + tagname + "' as boolean for field '" + fielddef.getName() + "'.", ex);
545
        }
546
        return defaultVaue;
547
    }
548

    
549
    protected String getTagValueAsString(String tagname, String defaultVaue) {
550
        return getTagValueAsString(tagname, null, defaultVaue);
551
    }
552

    
553
    protected String getTagValueAsString(String tagname1, String tagname2, String defaultVaue) {
554
        DynField_v2 fielddef = (DynField_v2) this.getDefinition();
555
        String tagname;
556
        if (fielddef.getTags().has(tagname1)) {
557
            tagname = tagname1;
558
        } else if (fielddef.getTags().has(tagname2)) {
559
            tagname = tagname2;
560
        } else {
561
            return defaultVaue;
562
        }
563
        try {
564
            String value = (String) fielddef.getTags().get(tagname, DataTypes.STRING);
565
            return value;
566
        } catch (CoercionException ex) {
567
            LOGGER.warn("Can't parse tag '" + tagname + "' as string for field '" + fielddef.getName() + "'.", ex);
568
        }
569
        return defaultVaue;
570
    }
571

    
572
    @Override
573
    public double getResizeWeight() {
574
        Tags tags = this.getDefinition().getTags();
575
        int resizeWeight = tags.getInt(DynFormSPIManager.TAG_DYNFORM_RESIZEWEIGHT, 0);
576
        if( resizeWeight<1 ) {
577
            return 0;
578
        }
579
        if( resizeWeight>100 ) {
580
            return 1;
581
        }
582
        return resizeWeight / 100.0;
583
    }
584

    
585
    @Override
586
    public void focusGained(FocusEvent arg0) {
587
        fireFieldEnterEvent();
588
        this.problemIndicator().restore();
589
    }
590

    
591
    @Override
592
    public void focusLost(FocusEvent arg0) {
593
        if (this.hasValidValue()) {
594
            this.problemIndicator().clear();
595
        } else {
596
            try {
597
                Object value = this.getValue();
598
            } catch (Exception e) {
599
                this.problemIndicator().set(e.getLocalizedMessage());
600
            }
601
        }
602
        fireFieldExitEvent();
603
    }
604

    
605
    protected void fixPreferredWidth(JComponent comp)  {
606
        Dimension prefsize = comp.getPreferredSize();
607
        if( prefsize.width>200 ) {
608
            prefsize.width = 200;
609
            comp.setPreferredSize(prefsize);
610
        }        
611
    }
612

    
613
    protected ImageIcon getIcon(String name) {
614
        IconThemeManager iconThemeManager = ToolsSwingLocator.getIconThemeManager();
615
        IconTheme theme = iconThemeManager.getCurrent();
616
        ImageIcon icon = theme.get(name);
617
        return icon;
618
    }
619
    
620
}