Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / featureform / swing / impl / DefaultJFeaturesForm.java @ 46959

History | View | Annotate | Download (49.9 KB)

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

    
25
import java.awt.BorderLayout;
26
import java.awt.Dimension;
27
import java.awt.event.ActionEvent;
28
import java.awt.event.ActionListener;
29
import java.awt.event.ComponentAdapter;
30
import java.awt.event.ComponentEvent;
31
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.List;
34
import java.util.Map;
35
import javax.swing.AbstractAction;
36
import javax.swing.Action;
37
import static javax.swing.Action.ACTION_COMMAND_KEY;
38
import static javax.swing.Action.NAME;
39
import static javax.swing.Action.SHORT_DESCRIPTION;
40
import static javax.swing.Action.SMALL_ICON;
41
import javax.swing.JComponent;
42
import javax.swing.JOptionPane;
43
import javax.swing.JPanel;
44
import org.apache.commons.lang3.StringUtils;
45
import org.gvsig.expressionevaluator.Expression;
46
import org.gvsig.expressionevaluator.ExpressionEvaluator;
47
import org.gvsig.expressionevaluator.ExpressionUtils;
48
import org.gvsig.featureform.swing.JFeaturesForm;
49
import org.gvsig.fmap.dal.DALLocator;
50
import org.gvsig.fmap.dal.DataStore;
51
import org.gvsig.fmap.dal.EditingNotification;
52
import static org.gvsig.fmap.dal.EditingNotification.AFTER_REMOVE_FEATURE;
53
import static org.gvsig.fmap.dal.EditingNotification.AFTER_UPDATE_FEATURE;
54
import static org.gvsig.fmap.dal.EditingNotification.AFTER_INSERT_FEATURE;
55
import static org.gvsig.fmap.dal.EditingNotification.AFTER_ENTER_EDITING_STORE;
56
import static org.gvsig.fmap.dal.EditingNotification.AFTER_EXIT_EDITING_STORE;
57
import static org.gvsig.fmap.dal.EditingNotification.BEFORE_REMOVE_FEATURE;
58
import static org.gvsig.fmap.dal.EditingNotification.BEFORE_UPDATE_FEATURE;
59
import static org.gvsig.fmap.dal.EditingNotification.BEFORE_INSERT_FEATURE;
60
import static org.gvsig.fmap.dal.EditingNotification.BEFORE_ENTER_EDITING_STORE;
61
import static org.gvsig.fmap.dal.EditingNotification.BEFORE_EXIT_EDITING_STORE;
62
import org.gvsig.fmap.dal.EditingNotificationManager;
63
import org.gvsig.fmap.dal.exception.DataException;
64
import org.gvsig.fmap.dal.feature.EditableFeature;
65
import org.gvsig.fmap.dal.feature.FacadeOfAFeature;
66
import org.gvsig.fmap.dal.feature.Feature;
67
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
68
import org.gvsig.fmap.dal.feature.FeatureQuery;
69
import org.gvsig.fmap.dal.feature.FeatureSelection;
70
import org.gvsig.fmap.dal.feature.FeatureStore;
71
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
72
import org.gvsig.fmap.dal.feature.FeatureType;
73
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
74
import org.gvsig.fmap.dal.swing.AbstractDALActionFactory.AbstractDALActionContext;
75
import org.gvsig.fmap.dal.swing.DALActionFactory;
76
import org.gvsig.fmap.dal.swing.DALSwingLocator;
77
import org.gvsig.fmap.dal.swing.DataSwingManager;
78
import org.gvsig.fmap.dal.swing.impl.DefaultDataSwingManager;
79
import org.gvsig.fmap.dal.swing.impl.actions.ShowFormAction.ShowFormActionFactory;
80
import org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel;
81
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
82
import org.gvsig.tools.ToolsLocator;
83
import org.gvsig.tools.dispose.Disposable;
84
import org.gvsig.tools.dispose.DisposeUtils;
85
import org.gvsig.tools.dynform.AbortActionException;
86
import org.gvsig.tools.dynform.DynFormDefinition;
87
import org.gvsig.tools.dynform.DynFormLocator;
88
import org.gvsig.tools.dynform.DynFormManager;
89
import org.gvsig.tools.dynform.JDynForm;
90
import org.gvsig.tools.dynform.JDynFormField;
91
import org.gvsig.tools.dynform.JDynFormSet;
92
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_CANCEL_NEW;
93
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_DELETE;
94
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_NAVIGATION;
95
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_NEW;
96
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_SAVE;
97
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_SEARCH;
98
import org.gvsig.tools.dynform.JDynFormSet.JDynFormSetListener;
99
import org.gvsig.tools.dynobject.DynClass;
100
import org.gvsig.tools.dynobject.DynObject;
101
import org.gvsig.tools.evaluator.Evaluator;
102
import org.gvsig.tools.exception.BaseException;
103
import org.gvsig.tools.i18n.I18nManager;
104
import org.gvsig.tools.observer.Observable;
105
import org.gvsig.tools.observer.Observer;
106
import org.gvsig.tools.swing.api.ActionListenerSupport;
107
import org.gvsig.tools.swing.api.ToolsSwingLocator;
108
import org.gvsig.tools.swing.api.ToolsSwingUtils;
109
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
110
import org.gvsig.tools.swing.api.windowmanager.Dialog;
111
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
112
import org.gvsig.tools.swing.api.windowmanager.WindowManager.MODE;
113
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
114
import org.gvsig.tools.swing.icontheme.IconTheme;
115
import org.gvsig.tools.util.PropertiesSupport;
116
import org.gvsig.tools.util.PropertiesSupportHelper;
117
import org.slf4j.Logger;
118
import org.slf4j.LoggerFactory;
119

    
120
/**
121
 * @author fdiaz
122
 *
123
 */
124
@SuppressWarnings("UseSpecificCatch")
125
public class DefaultJFeaturesForm implements JFeaturesForm, Disposable {
126

    
127
    private final String STARTEDITING_ACTION = "startEditing";
128
    private final String FINISHEDITING_ACTION = "finishEditing";
129
    private final String REFRESHFORM_ACTION = "refreshForm";
130
    
131
    private class JFeaturesFormPanel extends JPanel implements PropertiesSupport {
132

    
133
        private final PropertiesSupport properties;
134
        
135
        private JFeaturesFormPanel(PropertiesSupport properties, BorderLayout layout) {
136
            super(layout);
137
            this.properties = properties;
138
        }
139

    
140
        @Override
141
        public Object getProperty(String name) {
142
            return this.properties.getProperty(name);
143
        }
144

    
145
        @Override
146
        public void setProperty(String name, Object value) {
147
            this.properties.setProperty(name, value);
148
        }
149

    
150
        @Override
151
        public Map<String, Object> getProperties() {
152
            return this.properties.getProperties();
153
        }
154
        
155
    }
156
    
157
    private class FormActionContext extends AbstractDALActionContext {
158

    
159
        public FormActionContext() {
160
            super(ACTION_CONTEXT_NAME);
161
        }
162

    
163
        @Override
164
        public DataStore getStore() {
165
            return store;
166
        }
167

    
168
        @Override
169
        public FeatureQuery getQuery() {
170
            return currentQuery;
171
        }
172

    
173
        @Override
174
        public int getSelectedsCount() {
175
            return 0;
176
        }
177

    
178
        @Override
179
        public Expression getFilterForSelecteds() {
180
            return null;
181
        }
182

    
183
        @Override
184
        public FeatureSelection getSelecteds() {
185
            try {
186
                FeatureSelection selection = getFeatureStore().createFeatureSelection();
187
                selection.select(getCurrentFeature());
188
                return selection;
189
            } catch (DataException ex) {
190
                return null;
191
            }
192
        }
193

    
194
        @Override
195
        public JComponent getActionButton(String actionName) {
196
            if (formset == null) {
197
                return null;
198
            }
199
            return formset.getActionButton(actionName);
200
        }
201

    
202
    }
203

    
204
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJFeaturesForm.class);
205

    
206
    private static final int PAGE_SIZE = 10;
207
    private JFeaturesFormPanel panel;
208
    private JDynFormSet formset;
209
    private FeatureStore store;
210
    private boolean needrefresh;
211
    private FeaturePagingHelper features;
212
    private DynFormDefinition definition = null;
213
    private FeatureQuery currentQuery;
214
    private List<Action> otherActions;
215
    private final ActionListenerSupport actionListeners;
216
    private final PropertiesSupportHelper propertiesHelper;
217
    private boolean terminateEditingOnClose = true;
218
    private boolean ignoreTerminateEditingOnClose = false;
219

    
220
    @SuppressWarnings("LeakingThisInConstructor")
221
    public DefaultJFeaturesForm() {
222
        this.otherActions = new ArrayList<>();
223
        this.propertiesHelper = new PropertiesSupportHelper();
224
        this.propertiesHelper.setProperty("FeaturesForm", this);
225
        this.panel = new JFeaturesFormPanel(this.propertiesHelper, new BorderLayout());
226
        this.panel.addComponentListener(new ComponentAdapter() {
227
            @Override
228
            public void componentHidden(ComponentEvent e) {
229
                onClose();
230
                dispose();
231
            }
232
        });
233
        this.actionListeners = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
234
    }
235

    
236
    public static void selfRegister() {
237

    
238
    }
239

    
240
    @Override
241
    public void setPreferredSize(Dimension dimension) {
242
        panel.setPreferredSize(dimension);
243
    }
244

    
245
    private void updateForm() {
246
        if (this.formset == null) {
247
            this.getFormset();
248
        }
249
        try {
250
            if (this.currentQuery != null) {
251
                this.currentQuery.retrievesAllAttributes();
252
            }
253
            this.features = DALLocator.getDataManager().createFeaturePagingHelper(store, this.currentQuery, PAGE_SIZE);
254
            callUserEvent("form_beforeReload", this.formset.getForm());
255
            this.formset.setValues(features.asListOfDynObjects());
256
            callUserEvent("form_afterReload", this.formset.getForm());
257
        } catch (Exception ex) {
258
            throw new RuntimeException("Can't update form", ex);
259
        }
260
        this.needrefresh = false;
261
        updateButtonEnabledStatus();
262
    }
263

    
264
    @Override
265
    public JComponent asJComponent() {
266
        if (this.features == null) {
267
            try {
268
                updateForm();
269
            } catch (Exception ex) {
270
                throw new RuntimeException(ex);
271
            }
272
        }
273
        return this.panel;
274
    }
275

    
276
    @Override
277
    public void bind(FeatureStore store) {
278
        this.bind(store, null, null);
279
    }
280

    
281
    public void bind(FeatureStore store, DynClass definition) {
282
        this.bind(store, definition, null);
283
    }
284

    
285
    public void bind(FeatureStore store, DynClass definition, FeatureQuery query) {
286
        if (store == null) {
287
            throw new IllegalArgumentException("bind need a store as parameter, not a null.");
288
        }
289
        if (this.store == store) {
290
            return;
291
        }
292
        try {
293
            if(store.isEditing()){
294
                this.ignoreTerminateEditingOnClose = true;
295
            }
296
            if (definition == null) {
297
                DefaultDataSwingManager manager = (DefaultDataSwingManager) DALSwingLocator.getSwingManager();
298
                definition = manager.featureType2DynClass(store, store.getDefaultFeatureType());
299
            }
300
            DynFormManager formManager = DynFormLocator.getDynFormManager();
301
            this.definition = formManager.getDefinition(definition);
302
            if (formset != null) {
303
                this.panel.remove(formset.asJComponent());
304
                this.panel.revalidate();
305
                this.formset = null;
306
            }
307
            this.store = store;
308
            DisposeUtils.bind(store);
309
            this.currentQuery = query;
310
            if (features != null) {
311
                this.features = null;
312
                updateForm();
313
            }            
314
        } catch (Exception ex) {
315
            throw new RuntimeException("Can't bind store '" + store.getName() + "' to form", ex);
316
        }
317
    }
318

    
319
    @Override
320
    public void dispose() {
321
        if( this.formset!=null ) {
322
            Action action = this.formset.getAction(FINISHEDITING_ACTION);
323
            if( action!=null ) {
324
                DisposeUtils.disposeQuietly(action);
325
            }
326
            action = this.formset.getAction(STARTEDITING_ACTION);
327
            if( action!=null ) {
328
                DisposeUtils.disposeQuietly(action);
329
            }
330
        }
331
        if( this.panel!=null ) {
332
            this.panel.setVisible(false);
333
        }
334
        DisposeUtils.disposeQuietly(store);
335
        this.store = null;
336
        this.panel = null;
337
        this.formset = null;
338
        this.features = null;
339
        this.definition = null;
340
        this.currentQuery = null;
341
        this.otherActions = null;
342
    }
343

    
344
    public static class MyFeaturesFormContext extends DefaultFeaturesFormContext {
345

    
346
        private final DefaultJFeaturesForm featuresForm;
347
        
348
        public MyFeaturesFormContext(DefaultJFeaturesForm featuresForm) {
349
            super(featuresForm.store);
350
            this.featuresForm = featuresForm;
351
        }
352
        
353
        @Override
354
        public JFeaturesForm getFeaturesForm() {
355
            return this.featuresForm;
356
        }
357
        @Override
358
        public Feature getCurrentFeature() {    
359
            return this.featuresForm.getCurrentFeature();
360
        }
361
    }
362
    
363
    @Override
364
    public JDynFormSet getFormset() {
365
        if (this.formset == null) {
366
            DynFormManager formManager = DynFormLocator.getDynFormManager();
367
            this.formset = formManager.createJDynFormSet(
368
                    new MyFeaturesFormContext(this),
369
                    this.definition,
370
                    null
371
            );
372
            List<String> groups = this.definition.getGroups();
373
            if (groups.size() == 1 && groups.get(0) == null) {
374
                this.formset.setLayoutMode(JDynForm.USE_PLAIN);
375
            } else {
376
                this.formset.setLayoutMode(JDynForm.USE_TABS);
377
            }
378
            JComponent component = this.formset.getActionButton(JDynFormSet.ACTION_SET_CURRENT_RECORD);
379
            if( component!=null ) {
380
                I18nManager i18n = ToolsLocator.getI18nManager();
381
                component.setToolTipText(
382
                    "<html>" +
383
                    i18n.getTranslation("_Table") + ": " + this.store.getName() +"<br>\n"+
384
                    "( "+this.store.getFullName() + " )" +
385
                    "</html>"
386
                );
387
            }
388
            
389
            this.formset.setAllowNew(true);
390
            this.formset.setAllowDelete(true);
391
            this.formset.setAllowUpdate(true);
392
            this.formset.setAllowClose(true);
393
            this.formset.setAllowSearch(true);
394
            this.formset.setAutosave(true);
395

    
396
            this.formset.addAction(new StartEditingAction());
397
            this.formset.addAction(new FinishEditingAction());
398
            this.formset.addAction(new RefreshAction());
399

    
400
            FormActionContext actionContext = new FormActionContext();
401
            actionContext.set("featuresform", this);
402
            try {
403
                Collection<DALActionFactory> factories = DALSwingLocator.getSwingManager().getApplicableStoreActions(actionContext);
404
                for (DALActionFactory factory : factories) {
405
                    if (StringUtils.equalsIgnoreCase(factory.getName(), ShowFormActionFactory.ACTION_NAME)) {
406
                        continue;
407
                    }
408
                    try {
409
                        Action action = factory.createAction(actionContext);
410
                        this.formset.addAction(action);
411
                    } catch (Exception ex) {
412
                        LOGGER.warn("Can't add action " + factory.getName(), ex);
413
                    }
414

    
415
                }
416
            } catch (Exception ex) {
417
                LOGGER.warn("Can't add actions", ex);
418
            }
419
            for (Action action : this.otherActions) {
420
                this.formset.addAction(action);
421
            }
422

    
423
            this.formset.addListener(new FormSetListener());
424
            this.formset.getForm().addListener(new JDynForm.JDynFormListener() {
425
                @Override
426
                public void message(String string) {
427
                }
428

    
429
                @Override
430
                public void fieldChanged(JDynFormField jdff) {
431
                    updateButtonEnabledStatus();
432
                }
433
            });
434

    
435
            ToolsSwingLocator.getToolsSwingManager().removeBorder(this.formset.asJComponent());
436
            this.panel.add(this.formset.asJComponent(), BorderLayout.CENTER);
437
            this.panel.revalidate();
438
            ToolsSwingUtils.ensureRowsCols(this.panel, 8, 70, 25, 100);
439

    
440
        }
441
        updateButtonEnabledStatus();
442
        return this.formset;
443
    }
444

    
445
    @Override
446
    public void addAction(Action action) {
447
        this.otherActions.add(action);
448
        if (this.formset != null) {
449
            this.formset.addAction(action);
450
        }
451
    }
452

    
453
    @Override
454
    public long getCurrentIndex() {
455
        if (this.formset == null) {
456
            return -1;
457
        }
458
        return this.formset.getCurrentIndex();
459
    }
460

    
461
    @Override
462
    public Feature get(long index) {
463
        if (this.formset == null || this.features == null) {
464
            return null;
465
        }
466
        try {
467
            return this.features.getFeatureAt(index);
468
        } catch (BaseException ex) {
469
            return null;
470
        }
471
    }
472

    
473
    private class RefreshAction extends AbstractAction {
474

    
475
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
476
        public RefreshAction() {
477
            I18nManager i18nManager = ToolsLocator.getI18nManager();
478
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
479

    
480
            this.putValue(NAME, null);
481
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Reload_data"));
482
            this.putValue(SMALL_ICON, iconTheme.get("common-form-refresh"));
483
            this.putValue(ACTION_COMMAND_KEY, REFRESHFORM_ACTION);
484
            this.setEnabled(!formset.isInNewState());
485
        }
486

    
487
        @Override
488
        public void actionPerformed(ActionEvent ae) {
489
            try {
490
                I18nManager i18n = ToolsLocator.getI18nManager();
491
                formset.message(i18n.getTranslation("_Form_reloaded"));
492
                int x=formset.getCurrentIndex();
493
                updateForm();
494
                formset.setCurrentIndex(x);
495
            } catch (Exception ex) {
496
                LOGGER.warn("Can't reload form", ex);
497
            }
498
        }
499
    }
500

    
501
    private class FinishEditingAction extends AbstractAction implements Observer, Disposable {
502

    
503
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
504
        public FinishEditingAction() {
505
            I18nManager i18nManager = ToolsLocator.getI18nManager();
506
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
507

    
508
            this.putValue(NAME, null);
509
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Stop_editing"));
510
            this.putValue(SMALL_ICON, iconTheme.get("table-stop-editing"));
511
            this.putValue(ACTION_COMMAND_KEY, FINISHEDITING_ACTION);
512

    
513
            this.setEnabled(store.isEditing());
514
            store.addObserver(this);
515
        }
516

    
517
        @Override
518
        public void actionPerformed(ActionEvent ae) {
519
            if (store == null || formset == null) {
520
                return;
521
            }
522
            if (store.isEditing()) {
523
                EditingNotificationManager editingManager = DALSwingLocator.getEditingNotificationManager();
524
                DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
525
                ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
526
                I18nManager i18nManager = ToolsLocator.getI18nManager();
527
                try {
528
                    int x = dataSwingManager.askUserStopEditing(formset.asJComponent(), store, true);
529
                    switch (x) {
530
                        case DataSwingManager.STOP_EDITING_SAVE:
531
                            EditingNotification notification = editingManager.notifyObservers(this, BEFORE_EXIT_EDITING_STORE, null, store);
532
                            if( notification.isCanceled()) {
533
                                I18nManager i18n = ToolsLocator.getI18nManager();
534
                                formset.message(i18n.getTranslation("Finish editing has been cancelled."));
535
                                return;
536
                            }                
537
                            store.finishEditing();
538
                            editingManager.notifyObservers(this, AFTER_EXIT_EDITING_STORE, null, store);
539
                            break;
540
                        case DataSwingManager.STOP_EDITING_CONTINUE:
541
                            break;
542
                        case DataSwingManager.STOP_EDITING_DISCARD:
543
                            store.cancelEditing();
544
                            int index = formset.getCurrentIndex();
545
                            try {
546
                                formset.setCurrentIndex(index);
547
                            } catch (Exception ex) {
548
                                LOGGER.warn("Can't reload form data after edit.", ex);
549
                            }
550
                            break;
551
                        case DataSwingManager.STOP_EDITING_EXPORT:
552
                            if( !((DefaultDataSwingManager)dataSwingManager).exportStore(store, MODE.DIALOG) ) {
553
                                // Mensaje de operacion no soportada
554
                            }
555
                    }
556
                } catch (Exception ex) {
557
                    LOGGER.warn("Can't finish editing in FeatureForm (" + store.getName() + ").", ex);
558
                    dialogManager.messageDialog(
559
                            i18nManager.getTranslation("_Problems_finish_table_editing") + "\n\n"
560
                            + i18nManager.getTranslation("_see_error_log_for_more_information"),
561
                            i18nManager.getTranslation("_Stop_editing"),
562
                            JOptionPane.ERROR_MESSAGE
563
                    );
564
                }
565
            }
566
            updateButtonEnabledStatus();
567
        }
568

    
569
        @Override
570
        public void update(Observable observable, Object notification) {
571
            if (store == null || formset == null) {
572
                return;
573
            }
574
            if (notification instanceof FeatureStoreNotification) {
575
                FeatureStoreNotification n = (FeatureStoreNotification) notification;
576
                switch (n.getType()) {
577
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
578
                        needrefresh = true;
579
                    case FeatureStoreNotification.AFTER_STARTEDITING:
580
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
581
                        updateButtonEnabledStatus();
582
                        break;
583
                }
584
            }
585
        }
586

    
587
        @Override
588
        public void dispose() {
589
            store.deleteObserver(this);
590
        }
591

    
592
    }
593

    
594
    private class StartEditingAction extends AbstractAction implements Observer, Disposable {
595

    
596
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
597
        public StartEditingAction() {
598
            I18nManager i18nManager = ToolsLocator.getI18nManager();
599
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
600

    
601
            this.putValue(NAME, null);
602
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Start_editing"));
603
            this.putValue(SMALL_ICON, iconTheme.get("table-start-editing"));
604
            this.putValue(ACTION_COMMAND_KEY, STARTEDITING_ACTION);
605

    
606
            this.setEnabled(!store.isEditing());
607
            store.addObserver(this);
608
        }
609

    
610
        @Override
611
        public void actionPerformed(ActionEvent ae) {
612
            if (store == null || formset == null) {
613
                return;
614
            }
615
            if (!store.isEditing()) {
616
                try {
617
                    EditingNotificationManager editingManager = DALSwingLocator.getEditingNotificationManager();
618
                    EditingNotification notification = editingManager.notifyObservers(this, BEFORE_ENTER_EDITING_STORE, null, store);
619
                    if( notification.isCanceled() ) {
620
                        I18nManager i18n = ToolsLocator.getI18nManager();
621
                        formset.message(i18n.getTranslation("Enter editing has been cancelled."));
622
                        return;
623
                    }                
624
                    store.edit();
625
                    editingManager.notifyObservers(this, AFTER_ENTER_EDITING_STORE, null, store);
626
                } catch (DataException ex) {
627
                    LOGGER.warn("Can't finish editing in FeatureForm (" + store.getName() + ").", ex);
628
                }
629
            }
630
            updateButtonEnabledStatus();
631
        }
632

    
633
        @Override
634
        public void update(Observable observable, Object notification) {
635
            if (store == null || formset == null) {
636
                return;
637
            }
638
            if (notification instanceof FeatureStoreNotification) {
639
                FeatureStoreNotification n = (FeatureStoreNotification) notification;
640
                switch (n.getType()) {
641
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
642
                        needrefresh = true;
643
                    case FeatureStoreNotification.AFTER_STARTEDITING:
644
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
645
                        updateButtonEnabledStatus();
646
                        break;
647
                }
648
            }
649
        }
650

    
651
        @Override
652
        public void dispose() {
653
            store.deleteObserver(this);
654
        }
655

    
656
    }
657

    
658
    @Override
659
    public void setQuery(FeatureQuery query) {
660
        if (this.features != null) {
661
            if (this.formset != null && !formset.isReadOnly() && this.formset.isAutosave() && this.formset.countValues() > 0) {
662
                if(this.formset.getForm().isModified()){
663
                    if (!store.isEditing()) {
664
                        try {
665
                            store.edit();
666
                        } catch (DataException e1) {
667
                            throw new RuntimeException("Can't set query", e1);
668
                        }
669
                    }
670
                    saveChanges(this.formset);
671
                }
672
            }
673
        }
674
        this.currentQuery = query;
675
        updateForm();
676
    }
677

    
678
    private FeatureQuery getCurrentQuery() {
679
        return this.currentQuery;
680
    }
681

    
682
    @Override
683
    public void showForm(MODE mode) {
684
        I18nManager i18n = ToolsLocator.getI18nManager();
685
        String title = i18n.getTranslation("_Form") + ": "+ this.definition.getLabel();
686
        showForm(title, mode);
687
    }
688

    
689
    @Override
690
    public void showForm(String title, MODE mode) {
691
        WindowManager winmgr = ToolsSwingLocator.getWindowManager();
692
        if( StringUtils.isBlank(title) ) {
693
            title = this.definition.getLabel();
694
        }
695
        winmgr.showWindow(this.asJComponent(), title, mode);
696
    }
697
    
698
    @Override
699
    public void hideForm() {
700
        DisposeUtils.dispose(this);
701
    }
702

    
703
    private void saveChanges(JDynFormSet theFormSet) {
704
        I18nManager i18n = ToolsLocator.getI18nManager();
705
        try {
706
            EditingNotificationManager editingManager = DALSwingLocator.getEditingNotificationManager();
707
            if (theFormSet.isInNewState()) {
708
                EditableFeature newFeature = store.createNewFeature(false);
709
                JDynForm form = formset.getForm();
710
                for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
711
                    String name = attr.getName();
712
                    if( !newFeature.canSetValue(name) ) {
713
                        continue;
714
                    }
715
                    JDynFormField field = form.getField(name);
716
                    if( field==null ) {
717
                        // The attribute is not in form, set default value
718
                        newFeature.set(name, attr.getDefaultValueCoerced());
719
                    } else {
720
                        try {
721
                            Object value = field.getValue();
722
                            newFeature.set(name, value);
723
                        } catch (Exception ex) {
724
                            LOGGER.warn("Can't get value of field '" + name + "'.", ex);
725
                        }
726
                    }
727
                }
728
                EditingNotification notification = editingManager.notifyObservers(this, BEFORE_INSERT_FEATURE, null, this.store, newFeature);
729
                if( notification.isCanceled() ) {
730
                    theFormSet.message(i18n.getTranslation("Data saving has been cancelled."));
731
                    return;
732
                }                
733
                if (!editingManager.canWriteFeature(newFeature)) {
734
                    theFormSet.message(i18n.getTranslation("The data cannot be saved. Check that all the required fields are filled out.."));
735
                    return;
736
                }
737
                features.insert(newFeature);
738
                editingManager.notifyObservers(this, AFTER_INSERT_FEATURE, null, this.store, newFeature);
739
                
740
                this.formset.message(i18n.getTranslation("_Record_saved"));
741
                try {
742
                    this.formset.setValues(features.asListOfDynObjects());
743
                    this.formset.setCurrentIndex((int) (features.getTotalSize()) - 1);
744
                } catch (Exception ex) {
745
                    LOGGER.warn("Can't reload form data after insert.", ex);
746
                }
747
            } else {
748
                int index = theFormSet.getCurrentIndex();
749
                DynObject currentElement = theFormSet.get(index);
750
                theFormSet.getFormValues(currentElement);
751

    
752
                EditableFeature feature = ((FacadeOfAFeature) currentElement).getEditableFeature();
753
                EditingNotification notification = editingManager.notifyObservers(this, BEFORE_UPDATE_FEATURE, null, this.store, feature);
754
                if( notification.isCanceled() ) {
755
                    theFormSet.message(i18n.getTranslation("Data saving has been cancelled."));
756
                    return;
757
                }                
758
                if (!editingManager.canWriteFeature(feature)) {
759
                    theFormSet.message(i18n.getTranslation("The data cannot be saved. Check that all the required fields are filled out.."));
760
                    return;
761
                }
762
                features.update(feature);
763
                editingManager.notifyObservers(this, AFTER_UPDATE_FEATURE, null, this.store, feature);
764

    
765
                this.formset.message(i18n.getTranslation("_Record_saved"));
766
                try {
767
                    this.formset.setCurrentIndex(index);
768
                } catch (Exception ex) {
769
                    LOGGER.warn("Can't reload form data after insert.", ex);
770
                }
771
            }
772
        } catch (Exception ex) {
773
            theFormSet.message(i18n.getTranslation("error_saving_data_will_not_save"));
774
            throw new RuntimeException("Can't save values", ex);
775

    
776
        } finally {
777
            updateButtonEnabledStatus();
778
        }
779

    
780
    }
781

    
782
    private void deleteCurrentElement(JDynFormSet theFormSet) {
783
        I18nManager i18n = ToolsLocator.getI18nManager();
784
        try {
785
            EditingNotificationManager editingManager = DALSwingLocator.getEditingNotificationManager();
786
            int index = theFormSet.getCurrentIndex();
787
            DynObject currentElement = theFormSet.get(index);
788
            theFormSet.getFormValues(currentElement);
789
            Feature feature = ((FacadeOfAFeature) currentElement).getFeature();
790
            if (feature instanceof EditableFeature) {
791
                feature = ((EditableFeature) feature).getNotEditableCopy();
792
            }
793
            if( editingManager.notifyObservers(this, BEFORE_REMOVE_FEATURE, null, this.store, feature).isCanceled() ) {
794
                theFormSet.message(i18n.getTranslation("The delete operation has been cancelled."));
795
                return;
796
            }                
797
            features.delete(feature);
798
            editingManager.notifyObservers(this, AFTER_REMOVE_FEATURE, null, this.store, feature);
799

    
800
            this.formset.message(i18n.getTranslation("_Record_removed"));
801

    
802
            this.formset.setValues(features.asListOfDynObjects());
803
            if (features.getTotalSize() - 1 < index) {
804
                index = index - 1;
805
            }
806
            this.formset.setCurrentIndex(index);
807

    
808
        } catch (Exception ex) {
809
            theFormSet.message(i18n.getTranslation("error_removing_data_will_not_remove"));
810
            throw new RuntimeException("Can't remove values", ex);
811

    
812
        } finally {
813
            updateButtonEnabledStatus();
814
        }
815

    
816
    }
817

    
818
    @Override
819
    public void saveChanges() {
820
        if (this.formset != null && this.formset.countValues() > 0) {
821
            if (store != null && !store.isEditing()) {
822
                try {
823
                    store.edit();
824
                } catch (DataException e1) {
825
                    LOGGER.warn("Can't edit the store " + store.getName());
826
                    throw new RuntimeException("Can't save changes.", e1);
827
                }
828
            }
829
            this.saveChanges(this.formset);
830
        }
831
    }
832

    
833
    private void updateButtonEnabledStatus() {
834
        if (this.formset == null) {
835
            return;
836
        }
837
        if (this.store == null || store.isBroken() || store.isAppending() || this.features == null) {
838
            this.formset.setReadOnly(true);
839
            formset.setActionVisible(STARTEDITING_ACTION, true);
840
            formset.setActionEnabled(STARTEDITING_ACTION, true);
841
            formset.setActionVisible(FINISHEDITING_ACTION, false);
842
            formset.setActionEnabled(FINISHEDITING_ACTION, false);
843
            formset.setActionEnabled(ACTION_DELETE, false);
844
            formset.setActionEnabled(ACTION_NEW, false);
845
            formset.setActionEnabled(ACTION_CANCEL_NEW, false);
846
            formset.setActionEnabled(ACTION_SAVE, false);
847
            formset.setActionEnabled(ACTION_SEARCH, false);
848
            formset.setActionEnabled(REFRESHFORM_ACTION, true);
849
            formset.setActionEnabled(ACTION_NAVIGATION, false);
850
            return;
851
        }
852
        if (this.needrefresh ) {
853
            this.formset.setReadOnly(true);
854
//            formset.setActionEnabled(STARTEDITING_ACTION, false);
855
//            formset.setActionEnabled(FINISHEDITING_ACTION, false);
856
            formset.setActionEnabled(ACTION_DELETE, false);
857
            formset.setActionEnabled(ACTION_NEW, false);
858
            formset.setActionEnabled(ACTION_CANCEL_NEW, false);
859
            formset.setActionEnabled(ACTION_SAVE, false);
860
            formset.setActionEnabled(ACTION_SEARCH, false);
861
            formset.setActionEnabled(ACTION_NAVIGATION, false);
862
            for (Action action : formset.getActions()) {
863
                formset.setActionEnabled((String) action.getValue(ACTION_COMMAND_KEY), false);
864
            }
865
            formset.setActionEnabled(REFRESHFORM_ACTION, true);
866
            return;
867
        }
868
        if (store.isEditing()) {
869
            this.formset.setReadOnly(false);
870
            formset.setActionVisible(STARTEDITING_ACTION, false);
871
            formset.setActionEnabled(STARTEDITING_ACTION, false);
872
            formset.setActionVisible(FINISHEDITING_ACTION, true);
873
            formset.setActionEnabled(FINISHEDITING_ACTION, true);
874
            if (formset.isInNewState()) {
875
                formset.setActionEnabled(ACTION_DELETE, false);
876
                formset.setActionEnabled(ACTION_SEARCH, false);
877
                formset.setActionEnabled(ACTION_NEW, false);
878
                formset.setActionEnabled(ACTION_CANCEL_NEW, true);
879
                formset.setActionEnabled(ACTION_SAVE, true);
880
                formset.setActionEnabled(FINISHEDITING_ACTION, false);
881
                formset.setActionEnabled(REFRESHFORM_ACTION, false);
882
//                setEnabledUniqueFields(true);
883

    
884
            } else if (this.features != null && this.features.isEmpty()) {
885
                formset.getForm().setReadOnly(true);
886
                formset.setActionEnabled(ACTION_DELETE, false);
887
                formset.setActionEnabled(ACTION_SEARCH, false);
888
                formset.setActionEnabled(ACTION_NEW, true);
889
                formset.setActionEnabled(ACTION_CANCEL_NEW, true);
890
                formset.setActionEnabled(ACTION_SAVE, false);
891
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
892
                formset.setActionEnabled(FINISHEDITING_ACTION, true);         
893
                formset.setActionEnabled(ACTION_NAVIGATION, false);
894

    
895
            } else if (formset.getForm().isModified()) {
896
                formset.setActionEnabled(ACTION_DELETE, false);
897
                formset.setActionEnabled(ACTION_SEARCH, false);
898
                formset.setActionEnabled(ACTION_NEW, false);
899
                formset.setActionEnabled(ACTION_CANCEL_NEW, false);
900
                formset.setActionEnabled(ACTION_SAVE, true);
901
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
902
                formset.setActionEnabled(FINISHEDITING_ACTION, false);
903
                formset.setActionEnabled(ACTION_NAVIGATION, false);
904

    
905
            } else {
906
                formset.setActionEnabled(ACTION_DELETE, true);
907
                formset.setActionEnabled(ACTION_SEARCH, true);
908
                formset.setActionEnabled(ACTION_NEW, true);
909
                formset.setActionEnabled(ACTION_CANCEL_NEW, false);
910
                formset.setActionEnabled(ACTION_SAVE, false);
911
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
912
                formset.setActionEnabled(FINISHEDITING_ACTION, true);
913
                formset.setActionEnabled(ACTION_NAVIGATION, true);
914
            }
915

    
916
            return;
917
        }
918
        this.formset.setReadOnly(true);
919
        formset.setActionVisible(STARTEDITING_ACTION, true);
920
        formset.setActionEnabled(STARTEDITING_ACTION, true);
921
        formset.setActionVisible(FINISHEDITING_ACTION, false);
922
        formset.setActionEnabled(FINISHEDITING_ACTION, false);
923
        formset.setActionEnabled(ACTION_DELETE, false);
924
        formset.setActionEnabled(ACTION_NEW, false);
925
        formset.setActionEnabled(ACTION_CANCEL_NEW, false);
926
        formset.setActionEnabled(ACTION_SAVE, false);
927
        formset.setActionEnabled(ACTION_SEARCH, true);
928
        formset.setActionEnabled(REFRESHFORM_ACTION, true);
929
        for (Action action : formset.getActions()) {
930
            formset.setActionEnabled((String) action.getValue(ACTION_COMMAND_KEY), true);
931
        }
932
        
933
    }
934

    
935
    private void clearUniqueFields() {
936
        for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
937
            if ((attr.isPrimaryKey() && !attr.isAutomatic()) || (attr.isIndexed() && !attr.allowIndexDuplicateds())) {
938
                JDynFormField field = formset.getForm().getField(attr.getName());
939
                if (field != null) {
940
                    field.clear();
941
                }
942
            }
943
        }
944
    }
945

    
946
    private void setEnabledUniqueFields(boolean enabled) {
947
        for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
948
            if ((attr.isPrimaryKey() && !attr.isAutomatic()) || (attr.isIndexed() && !attr.allowIndexDuplicateds())) {
949
                JDynFormField field = formset.getForm().getField(attr.getName());
950
                if (field != null) {
951
                    field.setReadOnly(!enabled);
952
                }
953
            }
954
        }
955
    }
956

    
957
    @Override
958
    public long getDataSetSize() {
959
        if (this.features != null) {
960
            return features.getTotalSize();
961
        }
962
        return 0;
963
    }
964

    
965
    @Override
966
    public FeatureStore getFeatureStore() {
967
        return this.store;
968
    }
969
    
970
    public FeatureType getFeatureType() {
971
        if( this.store == null ) {
972
            return null;
973
        }
974
        return this.store.getDefaultFeatureTypeQuietly();
975
    }
976

    
977
    private class FormSetListener implements JDynFormSetListener {
978

    
979
        @Override
980
        public void formMessage(String message) {
981
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formMessage"));
982
        }
983

    
984
        @Override
985
        public void formClose() {
986
            panel.setVisible(false);
987
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formClose"));
988
        }
989

    
990
        @Override
991
        public void formMovedTo(int currentPosition) throws AbortActionException {
992
            LOGGER.trace("formMovedTo " + currentPosition);
993
            updateButtonEnabledStatus();
994
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formMovedTo"));
995
        }
996

    
997
        @Override
998
        public void formBeforeSave(JDynFormSet dynformSet) throws AbortActionException {
999
            LOGGER.trace("formBeforeSave");
1000
            saveChanges(dynformSet);
1001
            updateButtonEnabledStatus();
1002
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeSave"));
1003
        }
1004

    
1005
        @Override
1006
        public void formBeforeNew(JDynFormSet dynformSet) throws AbortActionException {
1007
            LOGGER.trace("formBeforeNew");
1008
            clearUniqueFields();
1009
            updateButtonEnabledStatus();
1010
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeNew"));
1011
        }
1012

    
1013
        @Override
1014
        public void formBeforeDelete(JDynFormSet dynformSet) throws AbortActionException {
1015
            LOGGER.trace("formBeforeDelete");
1016
            updateButtonEnabledStatus();
1017
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeDelete"));
1018
        }
1019

    
1020
        @Override
1021
        public void formAfterSave(JDynFormSet dynformSet) throws AbortActionException {
1022
            LOGGER.trace("formAfterSave");
1023
            updateButtonEnabledStatus();
1024
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterSave"));
1025
        }
1026

    
1027
        @Override
1028
        public void formAfterNew(JDynFormSet dynformSet) throws AbortActionException {
1029
            LOGGER.trace("formAfterNew");
1030
            updateButtonEnabledStatus();
1031
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterNew"));
1032
        }
1033

    
1034
        @Override
1035
        public void formAfterDelete(JDynFormSet dynformSet) throws AbortActionException {
1036
            LOGGER.trace("formAfterDelete");
1037
            deleteCurrentElement(dynformSet);
1038
            updateButtonEnabledStatus();
1039
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterDelete"));
1040
        }
1041

    
1042
        @Override
1043
        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
1044
            LOGGER.trace("formBeforeSearch");
1045
            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
1046
            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
1047

    
1048
            final FeatureStoreSearchPanel searchPanel = dataSwingmanager.createFeatureStoreSearchPanel(store);
1049
            searchPanel.setShowActions(false);
1050
            FeatureQuery currentQuery = getCurrentQuery();
1051
            if (currentQuery != null) {
1052
                Evaluator filter = currentQuery.getFilter();
1053
                if (filter instanceof ExpressionEvaluator) {
1054
                    Expression expression = ((ExpressionEvaluator) filter).toExpression();
1055
                    searchPanel.setFilter(expression);
1056
                    searchPanel.search();
1057
                }
1058
            }
1059
            ToolsSwingUtils.ensureRowsCols(searchPanel.asJComponent(), 20, 80, 35, 140);
1060
            I18nManager i18n = ToolsLocator.getI18nManager();
1061
            Dialog dialog = winmgr.createDialog(
1062
                    searchPanel.asJComponent(),
1063
                    i18n.getTranslation("_Filter"),
1064
                    i18n.getTranslation("_Creating_filter_for") + ": '" + store.getName() + "'",
1065
                    WindowManager_v2.BUTTONS_OK_CANCEL
1066
            );
1067
            dialog.show(WindowManager.MODE.DIALOG);
1068
            if (dialog.getAction() == WindowManager_v2.BUTTON_OK) {
1069
                SearchParameters params = searchPanel.fetch(null);
1070
                if (params.getQuery() != null) {
1071
                    FeatureQuery searchQuery = params.getQuery().getCopy();
1072

    
1073
                    Expression expresion = null;
1074
                    if (searchQuery != null) {
1075
                        expresion = searchQuery.getExpressionFilter();
1076
                    }
1077
                    try {
1078
                        FeatureQuery query = store.createFeatureQuery();
1079
                        if (ExpressionUtils.isPhraseEmpty(expresion)) {
1080
                            query.clearFilter();
1081
                        } else {
1082
                            query.setFilter(expresion);
1083
                        }
1084
                        setQuery(query);
1085
                    } catch (Exception ex) {
1086
                        LOGGER.warn("Can't apply filter '" + expresion + "'.", ex);
1087
                    }
1088
                } else {
1089
                    LOGGER.warn("FeatureQuery from parameters is null. Query is not applied to the JFeaturesFrom");
1090
                }
1091
            }
1092
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeSearch"));
1093
        }
1094

    
1095
        @Override
1096
        public void formAfterSearch(JDynFormSet dynformSet) throws AbortActionException {
1097
            LOGGER.trace("formAfterSearch");
1098
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterSearch"));
1099
        }
1100

    
1101
        @Override
1102
        public void formBeforeCancelNew(JDynFormSet dynformSet) throws AbortActionException {
1103
            LOGGER.trace("formBeforeCancelNew");
1104
            updateButtonEnabledStatus();
1105
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeCancelNew"));
1106
        }
1107

    
1108
        @Override
1109
        public void formAfterCancelNew(JDynFormSet dynformSet) throws AbortActionException {
1110
            LOGGER.trace("formAfterCancelNew");
1111
            try {
1112
                int index = formset.getCurrentIndex();
1113
                if( index<0 ) {
1114
                    formset.getForm().clear();
1115
                } else {
1116
                    formset.setCurrentIndex(index);
1117
                }
1118
            } catch (Exception ex) {
1119
                LOGGER.warn("Can't reload form data after cancel new.", ex);
1120
            }            
1121
            updateButtonEnabledStatus();
1122
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterCancelNew"));
1123
        }
1124

    
1125
    }
1126

    
1127
    @Override
1128
    public void addActionListener(ActionListener listener) {
1129
        this.actionListeners.addActionListener(listener);
1130
    }
1131

    
1132
    @Override
1133
    public ActionListener[] getActionListeners() {
1134
        return this.actionListeners.getActionListeners();
1135
    }
1136

    
1137
    @Override
1138
    public void removeActionListener(ActionListener listener) {
1139
        this.actionListeners.removeActionListener(listener);
1140
    }
1141

    
1142
    @Override
1143
    public void removeAllActionListener() {
1144
        this.actionListeners.removeAllActionListener();
1145
    }
1146

    
1147
    @Override
1148
    public void fireActionEvent(ActionEvent event) {
1149
        this.actionListeners.fireActionEvent(event);
1150
    }
1151

    
1152
    @Override
1153
    public boolean hasActionListeners() {
1154
        return this.actionListeners.hasActionListeners();
1155
    }
1156

    
1157
    @Override
1158
    public Feature getCurrentFeature() {
1159
        // TODO: No tengo claro que esto sea correcto, ya que no tiene 
1160
        // en cuenta si el form se esta modificando o es nuevo para coger
1161
        // los valores del formulario.
1162
        long index = getCurrentIndex();
1163
        if( index<0 ) {
1164
            return null;
1165
        }
1166
        Feature f = get(index);
1167
        try {
1168
            DynObject adapter = f.getAsDynObject();
1169
            this.getFormset().getForm().getValues(adapter);
1170
            f = ((FacadeOfAFeature)adapter).getFeature();
1171
            return f;
1172
        } catch(Exception ex) {
1173
            return f;
1174
        }
1175
    }
1176

    
1177
    protected void callUserEvent(String name, Object...args) {
1178
//        try {
1179
            JDynForm form = this.formset.getForm();
1180
            form.callUserEvent(name, args);
1181
//        } catch(NoSuchMethodException ex) {
1182
//            LOGGER.debug("Function '"+name+"' not found.", ex);
1183
//            // Do nothing
1184
//        } catch(Exception ex) {
1185
//            LOGGER.warn("Error calling form event '"+name+"'.", ex);
1186
//        }
1187
    }
1188
    
1189
    @Override
1190
    public void setTerminateEditingOnClose(boolean b) {
1191
        terminateEditingOnClose = b;
1192
    }
1193

    
1194
    @Override
1195
    public boolean isTerminateEditingOnClose() {
1196
        return terminateEditingOnClose;
1197
    }
1198

    
1199
    private void onClose() {
1200
        if (this.store == null || this.ignoreTerminateEditingOnClose) {
1201
            return;
1202
        }
1203
        if (this.store.isEditing() && terminateEditingOnClose) {
1204
            DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
1205
            ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
1206
            I18nManager i18nManager = ToolsLocator.getI18nManager();
1207
            try {
1208
                int x = dataSwingManager.askUserStopEditing(formset.asJComponent(), store, false);
1209
                switch (x) {
1210
                    case DataSwingManager.STOP_EDITING_SAVE:
1211
                        store.finishEditing();
1212
                        break;
1213
                    case DataSwingManager.STOP_EDITING_CONTINUE:
1214
                        break;
1215
                    case DataSwingManager.STOP_EDITING_DISCARD:
1216
                        store.cancelEditing();
1217
                        break;
1218
                    case DataSwingManager.STOP_EDITING_EXPORT:
1219
                        if( !((DefaultDataSwingManager)dataSwingManager).exportStore(store, MODE.DIALOG) ) {
1220
                            // Mensaje de operacion no soportada
1221
                        }
1222
                }
1223
            } catch (Exception ex) {
1224
                LOGGER.warn("Can't finish editing in FeatureForm (" + DataStore.getNameQuietly(store) + ").", ex);
1225
                dialogManager.messageDialog(
1226
                        i18nManager.getTranslation("_Problems_finish_table_editing") + "\n\n"
1227
                        + i18nManager.getTranslation("_see_error_log_for_more_information"),
1228
                        i18nManager.getTranslation("_Stop_editing"),
1229
                        JOptionPane.ERROR_MESSAGE
1230
                );
1231
            }
1232

    
1233
        }
1234
    }
1235

    
1236

    
1237
}