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

History | View | Annotate | Download (43.6 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.net.URL;
32
import java.util.ArrayList;
33
import java.util.Collection;
34
import java.util.List;
35
import java.util.Map;
36
import javax.swing.AbstractAction;
37
import javax.swing.Action;
38
import static javax.swing.Action.ACTION_COMMAND_KEY;
39
import static javax.swing.Action.NAME;
40
import static javax.swing.Action.SHORT_DESCRIPTION;
41
import static javax.swing.Action.SMALL_ICON;
42
import javax.swing.JComponent;
43
import javax.swing.JOptionPane;
44
import javax.swing.JPanel;
45
import org.apache.commons.lang3.StringUtils;
46
import org.gvsig.expressionevaluator.Expression;
47
import org.gvsig.expressionevaluator.ExpressionEvaluator;
48
import org.gvsig.expressionevaluator.ExpressionUtils;
49
import org.gvsig.featureform.swing.JFeaturesForm;
50
import org.gvsig.fmap.dal.DALLocator;
51
import org.gvsig.fmap.dal.DataStore;
52
import org.gvsig.fmap.dal.exception.DataException;
53
import org.gvsig.fmap.dal.feature.EditableFeature;
54
import org.gvsig.fmap.dal.feature.FacadeOfAFeature;
55
import org.gvsig.fmap.dal.feature.Feature;
56
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.FeatureQuery;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
60
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
61
import org.gvsig.fmap.dal.swing.AbstractDALActionFactory.AbstractDALActionContext;
62
import org.gvsig.fmap.dal.swing.DALActionFactory;
63
import org.gvsig.fmap.dal.swing.DALSwingLocator;
64
import org.gvsig.fmap.dal.swing.DataSwingManager;
65
import org.gvsig.fmap.dal.swing.impl.DefaultDataSwingManager;
66
import org.gvsig.fmap.dal.swing.impl.actions.ShowFormAction.ShowFormActionFactory;
67
import org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel;
68
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
69
import org.gvsig.tools.ToolsLocator;
70
import org.gvsig.tools.dispose.Disposable;
71
import org.gvsig.tools.dispose.DisposeUtils;
72
import org.gvsig.tools.dynform.AbortActionException;
73
import org.gvsig.tools.dynform.DynFormDefinition;
74
import org.gvsig.tools.dynform.DynFormLocator;
75
import org.gvsig.tools.dynform.DynFormManager;
76
import org.gvsig.tools.dynform.JDynForm;
77
import org.gvsig.tools.dynform.JDynFormField;
78
import org.gvsig.tools.dynform.JDynFormSet;
79
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_CANCEL_NEW;
80
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_DELETE;
81
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_NAVIGATION;
82
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_NEW;
83
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_SAVE;
84
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_SEARCH;
85
import org.gvsig.tools.dynform.JDynFormSet.JDynFormSetListener;
86
import org.gvsig.tools.dynobject.DynClass;
87
import org.gvsig.tools.dynobject.DynObject;
88
import org.gvsig.tools.evaluator.Evaluator;
89
import org.gvsig.tools.exception.BaseException;
90
import org.gvsig.tools.i18n.I18nManager;
91
import org.gvsig.tools.observer.Observable;
92
import org.gvsig.tools.observer.Observer;
93
import org.gvsig.tools.swing.api.ActionListenerSupport;
94
import org.gvsig.tools.swing.api.ToolsSwingLocator;
95
import org.gvsig.tools.swing.api.ToolsSwingUtils;
96
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
97
import org.gvsig.tools.swing.api.windowmanager.Dialog;
98
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
99
import org.gvsig.tools.swing.api.windowmanager.WindowManager.MODE;
100
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
101
import org.gvsig.tools.swing.icontheme.IconTheme;
102
import org.gvsig.tools.util.PropertiesSupport;
103
import org.gvsig.tools.util.PropertiesSupportHelper;
104
import org.slf4j.Logger;
105
import org.slf4j.LoggerFactory;
106

    
107
/**
108
 * @author fdiaz
109
 *
110
 */
111
@SuppressWarnings("UseSpecificCatch")
112
public class DefaultJFeaturesForm implements JFeaturesForm, Disposable {
113

    
114
    private final String STARTEDITING_ACTION = "startEditing";
115
    private final String FINISHEDITING_ACTION = "finishEditing";
116
    private final String REFRESHFORM_ACTION = "refreshForm";
117

    
118
    private class JFeaturesFormPanel extends JPanel implements PropertiesSupport {
119

    
120
        private final PropertiesSupport properties;
121
        
122
        private JFeaturesFormPanel(PropertiesSupport properties, BorderLayout layout) {
123
            super(layout);
124
            this.properties = properties;
125
        }
126

    
127
        @Override
128
        public Object getProperty(String name) {
129
            return this.properties.getProperty(name);
130
        }
131

    
132
        @Override
133
        public void setProperty(String name, Object value) {
134
            this.properties.setProperty(name, value);
135
        }
136

    
137
        @Override
138
        public Map<String, Object> getProperties() {
139
            return this.properties.getProperties();
140
        }
141
        
142
    }
143
    
144
    private class FormActionContext extends AbstractDALActionContext {
145

    
146
        public FormActionContext() {
147
            super(ACTION_CONTEXT_NAME);
148
        }
149

    
150
        @Override
151
        public DataStore getStore() {
152
            return store;
153
        }
154

    
155
        @Override
156
        public FeatureQuery getQuery() {
157
            return currentQuery;
158
        }
159

    
160
        @Override
161
        public int getSelectedsCount() {
162
            return 0;
163
        }
164

    
165
        @Override
166
        public Expression getFilterForSelecteds() {
167
            return null;
168
        }
169

    
170
        @Override
171
        public JComponent getActionButton(String actionName) {
172
            if (formset == null) {
173
                return null;
174
            }
175
            return formset.getActionButton(actionName);
176
        }
177

    
178
    }
179

    
180
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJFeaturesForm.class);
181

    
182
    private static final int PAGE_SIZE = 10;
183
    private JFeaturesFormPanel panel;
184
    private JDynFormSet formset;
185
    private FeatureStore store;
186
    private boolean needrefresh;
187
    private FeaturePagingHelper features;
188
    private DynFormDefinition definition = null;
189
    private FeatureQuery currentQuery;
190
    private List<Action> otherActions;
191
    private final ActionListenerSupport actionListeners;
192
    private final PropertiesSupportHelper propertiesHelper;
193

    
194
    @SuppressWarnings("LeakingThisInConstructor")
195
    public DefaultJFeaturesForm() {
196
        this.otherActions = new ArrayList<>();
197
        this.propertiesHelper = new PropertiesSupportHelper();
198
        this.propertiesHelper.setProperty("FeaturesForm", this);
199
        this.panel = new JFeaturesFormPanel(this.propertiesHelper, new BorderLayout());
200
        this.panel.addComponentListener(new ComponentAdapter() {
201
            @Override
202
            public void componentHidden(ComponentEvent e) {
203
                dispose();
204
            }
205
        });
206
        this.actionListeners = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
207
    }
208

    
209
    public static void selfRegister() {
210
        String[][] iconNames = new String[][]{
211
            new String[]{"dalswing", "form-refresh-data"}
212
        };
213
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
214
        for (String[] icon : iconNames) {
215
            URL url = DefaultJFeaturesForm.class.getResource(icon[1] + ".png");
216
            theme.registerDefault("DALSwing", icon[0], icon[1], null, url);
217
        }
218

    
219
    }
220

    
221
    @Override
222
    public void setPreferredSize(Dimension dimension) {
223
        panel.setPreferredSize(dimension);
224
    }
225

    
226
    private void updateForm() {
227
        if (this.formset == null) {
228
            this.getFormset();
229
        }
230
        try {
231
            if (this.currentQuery != null) {
232
                this.currentQuery.retrievesAllAttributes();
233
            }
234
            this.features = DALLocator.getDataManager().createFeaturePagingHelper(store, this.currentQuery, PAGE_SIZE);
235
            this.formset.setValues(features.asListOfDynObjects());
236
        } catch (Exception ex) {
237
            throw new RuntimeException("Can't update form", ex);
238
        }
239
        this.needrefresh = false;
240
        updateButtonEnabledStatus();
241
    }
242

    
243
    @Override
244
    public JComponent asJComponent() {
245
        if (this.features == null) {
246
            try {
247
                updateForm();
248
            } catch (Exception ex) {
249
                throw new RuntimeException(ex);
250
            }
251
        }
252
        return this.panel;
253
    }
254

    
255
    @Override
256
    public void bind(FeatureStore store) {
257
        this.bind(store, null, null);
258
    }
259

    
260
    public void bind(FeatureStore store, DynClass definition) {
261
        this.bind(store, definition, null);
262
    }
263

    
264
    public void bind(FeatureStore store, DynClass definition, FeatureQuery query) {
265
        if (store == null) {
266
            throw new IllegalArgumentException("bind need a store as parameter, not a null.");
267
        }
268
        if (this.store == store) {
269
            return;
270
        }
271
        try {
272
            if (definition == null) {
273
                DefaultDataSwingManager manager = (DefaultDataSwingManager) DALSwingLocator.getSwingManager();
274
                definition = manager.featureType2DynClass(store, store.getDefaultFeatureType());
275
            }
276
            DynFormManager formManager = DynFormLocator.getDynFormManager();
277
            this.definition = formManager.getDefinition(definition);
278
            if (formset != null) {
279
                this.panel.remove(formset.asJComponent());
280
                this.panel.revalidate();
281
                this.formset = null;
282
            }
283
            this.store = store;
284
            DisposeUtils.bind(store);
285
            this.currentQuery = query;
286
            if (features != null) {
287
                this.features = null;
288
                updateForm();
289
            }
290
        } catch (Exception ex) {
291
            throw new RuntimeException("Can't bind store '" + store.getName() + "' to form", ex);
292
        }
293
    }
294

    
295
    @Override
296
    public void dispose() {
297
        if( this.formset!=null ) {
298
            Action action = this.formset.getAction(FINISHEDITING_ACTION);
299
            if( action!=null ) {
300
                DisposeUtils.disposeQuietly(action);
301
            }
302
            action = this.formset.getAction(STARTEDITING_ACTION);
303
            if( action!=null ) {
304
                DisposeUtils.disposeQuietly(action);
305
            }
306
        }
307
        DisposeUtils.disposeQuietly(store);
308
        this.store = null;
309
        this.panel = null;
310
        this.formset = null;
311
        this.features = null;
312
        this.definition = null;
313
        this.currentQuery = null;
314
        this.otherActions = null;
315
    }
316

    
317
    public static class MyFeaturesFormContext extends DefaultFeaturesFormContext {
318

    
319
        private final DefaultJFeaturesForm featuresForm;
320
        
321
        public MyFeaturesFormContext(DefaultJFeaturesForm featuresForm) {
322
            super(featuresForm.store);
323
            this.featuresForm = featuresForm;
324
        }
325
        
326
        @Override
327
        public JFeaturesForm getFeaturesForm() {
328
            return this.featuresForm;
329
        }
330
        @Override
331
        public Feature getCurrentFeature() {    
332
            return this.featuresForm.getCurrentFeature();
333
        }
334
    }
335
    
336
    @Override
337
    public JDynFormSet getFormset() {
338
        if (this.formset == null) {
339
            DynFormManager formManager = DynFormLocator.getDynFormManager();
340
            this.formset = formManager.createJDynFormSet(
341
                    new MyFeaturesFormContext(this),
342
                    this.definition,
343
                    null
344
            );
345
            List<String> groups = this.definition.getGroups();
346
            if (groups.size() == 1 && groups.get(0) == null) {
347
                this.formset.setLayoutMode(JDynForm.USE_PLAIN);
348
            } else {
349
                this.formset.setLayoutMode(JDynForm.USE_TABS);
350
            }
351
            this.formset.setAllowNew(true);
352
            this.formset.setAllowDelete(true);
353
            this.formset.setAllowUpdate(true);
354
            this.formset.setAllowClose(true);
355
            this.formset.setAllowSearch(true);
356
            this.formset.setAutosave(true);
357

    
358
            this.formset.addAction(new StartEditingAction());
359
            this.formset.addAction(new FinishEditingAction());
360
            this.formset.addAction(new RefreshAction());
361

    
362
            FormActionContext actionContext = new FormActionContext();
363
            try {
364
                Collection<DALActionFactory> factories = DALSwingLocator.getSwingManager().getStoreActions();
365
                for (DALActionFactory factory : factories) {
366
                    if (factory == null || StringUtils.equalsIgnoreCase(factory.getName(), ShowFormActionFactory.ACTION_NAME)) {
367
                        continue;
368
                    }
369
                    try {
370
                        Action action = factory.createAction(actionContext);
371
                        this.formset.addAction(action);
372
                    } catch (Exception ex) {
373
                        LOGGER.warn("Can't add action " + factory.getName(), ex);
374
                    }
375
                }
376
            } catch (Exception ex) {
377
                LOGGER.warn("Can't add actions", ex);
378
            }
379
            for (Action action : this.otherActions) {
380
                this.formset.addAction(action);
381
            }
382

    
383
            this.formset.addListener(new FormSetListener());
384
            this.formset.getForm().addListener(new JDynForm.JDynFormListener() {
385
                @Override
386
                public void message(String string) {
387
                }
388

    
389
                @Override
390
                public void fieldChanged(JDynFormField jdff) {
391
                    updateButtonEnabledStatus();
392
                }
393
            });
394

    
395
            ToolsSwingLocator.getToolsSwingManager().removeBorder(this.formset.asJComponent());
396
            this.panel.add(this.formset.asJComponent(), BorderLayout.CENTER);
397
            this.panel.revalidate();
398
            ToolsSwingUtils.ensureRowsCols(this.panel, 8, 70, 25, 100);
399

    
400
        }
401
        updateButtonEnabledStatus();
402
        return this.formset;
403
    }
404

    
405
    @Override
406
    public void addAction(Action action) {
407
        this.otherActions.add(action);
408
        if (this.formset != null) {
409
            this.formset.addAction(action);
410
        }
411
    }
412

    
413
    @Override
414
    public long getCurrentIndex() {
415
        if (this.formset == null) {
416
            return -1;
417
        }
418
        return this.formset.getCurrentIndex();
419
    }
420

    
421
    @Override
422
    public Feature get(long index) {
423
        if (this.formset == null || this.features == null) {
424
            return null;
425
        }
426
        try {
427
            return this.features.getFeatureAt(index);
428
        } catch (BaseException ex) {
429
            return null;
430
        }
431
    }
432

    
433
    private class RefreshAction extends AbstractAction {
434

    
435
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
436
        public RefreshAction() {
437
            I18nManager i18nManager = ToolsLocator.getI18nManager();
438
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
439

    
440
            this.putValue(NAME, null);
441
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Reload_data"));
442
            this.putValue(SMALL_ICON, iconTheme.get("form-refresh-data"));
443
            this.putValue(ACTION_COMMAND_KEY, REFRESHFORM_ACTION);
444
            this.setEnabled(!formset.isInNewState());
445
        }
446

    
447
        @Override
448
        public void actionPerformed(ActionEvent ae) {
449
            try {
450
                I18nManager i18n = ToolsLocator.getI18nManager();
451
                formset.message(i18n.getTranslation("_Form_reloaded"));
452
                int x=formset.getCurrentIndex();
453
                updateForm();
454
                formset.setCurrentIndex(x);
455
            } catch (Exception ex) {
456
                LOGGER.warn("Can't reload form", ex);
457
            }
458
        }
459
    }
460

    
461
    private class FinishEditingAction extends AbstractAction implements Observer, Disposable {
462

    
463
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
464
        public FinishEditingAction() {
465
            I18nManager i18nManager = ToolsLocator.getI18nManager();
466
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
467

    
468
            this.putValue(NAME, null);
469
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Stop_editing"));
470
            this.putValue(SMALL_ICON, iconTheme.get("table-stop-editing"));
471
            this.putValue(ACTION_COMMAND_KEY, FINISHEDITING_ACTION);
472

    
473
            this.setEnabled(store.isEditing());
474
            store.addObserver(this);
475
        }
476

    
477
        @Override
478
        public void actionPerformed(ActionEvent ae) {
479
            if (store == null || formset == null) {
480
                return;
481
            }
482
            if (store.isEditing()) {
483
                ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
484
                I18nManager i18nManager = ToolsLocator.getI18nManager();
485
                try {
486
                    int x = dialogManager.confirmDialog(
487
                            i18nManager.getTranslation("_Do_you_want_to_finish_editing_and_save_the_changes") + "\n\n"
488
                            + i18nManager.getTranslation("_Press_cancel_to_cancel_editing_and_changes"),
489
                            i18nManager.getTranslation("_Stop_editing"),
490
                            JOptionPane.YES_NO_CANCEL_OPTION,
491
                            JOptionPane.QUESTION_MESSAGE
492
                    );
493
                    switch (x) {
494
                        case JOptionPane.YES_OPTION:
495
                            store.finishEditing();
496
                            break;
497
                        case JOptionPane.NO_OPTION:
498
                            break;
499
                        case JOptionPane.CANCEL_OPTION:
500
                            store.cancelEditing();
501
                            int index = formset.getCurrentIndex();
502
                            try {
503
                                formset.setCurrentIndex(index);
504
                            } catch (Exception ex) {
505
                                LOGGER.warn("Can't reload form data after edit.", ex);
506
                            }
507
                            break;
508
                    }
509
                } catch (Exception ex) {
510
                    LOGGER.warn("Can't finish editing in FeatureForm (" + store.getName() + ").", ex);
511
                    dialogManager.messageDialog(
512
                            i18nManager.getTranslation("_Problems_finish_table_editing") + "\n\n"
513
                            + i18nManager.getTranslation("_see_error_log_for_more_information"),
514
                            i18nManager.getTranslation("_Stop_editing"),
515
                            JOptionPane.ERROR_MESSAGE
516
                    );
517
                }
518
            }
519
            updateButtonEnabledStatus();
520
        }
521

    
522
        @Override
523
        public void update(Observable observable, Object notification) {
524
            if (store == null || formset == null) {
525
                return;
526
            }
527
            if (notification instanceof FeatureStoreNotification) {
528
                FeatureStoreNotification n = (FeatureStoreNotification) notification;
529
                switch (n.getType()) {
530
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
531
                        needrefresh = true;
532
                    case FeatureStoreNotification.AFTER_STARTEDITING:
533
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
534
                        updateButtonEnabledStatus();
535
                        break;
536
                }
537
            }
538
        }
539

    
540
        @Override
541
        public void dispose() {
542
            store.deleteObserver(this);
543
        }
544

    
545
    }
546

    
547
    private class StartEditingAction extends AbstractAction implements Observer, Disposable {
548

    
549
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
550
        public StartEditingAction() {
551
            I18nManager i18nManager = ToolsLocator.getI18nManager();
552
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
553

    
554
            this.putValue(NAME, null);
555
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Start_editing"));
556
            this.putValue(SMALL_ICON, iconTheme.get("table-start-editing"));
557
            this.putValue(ACTION_COMMAND_KEY, STARTEDITING_ACTION);
558

    
559
            this.setEnabled(!store.isEditing());
560
            store.addObserver(this);
561
        }
562

    
563
        @Override
564
        public void actionPerformed(ActionEvent ae) {
565
            if (store == null || formset == null) {
566
                return;
567
            }
568
            if (!store.isEditing()) {
569
                try {
570
                    store.edit();
571
                } catch (DataException ex) {
572
                    LOGGER.warn("Can't finish editing in FeatureForm (" + store.getName() + ").", ex);
573
                }
574
            }
575
            updateButtonEnabledStatus();
576
        }
577

    
578
        @Override
579
        public void update(Observable observable, Object notification) {
580
            if (store == null || formset == null) {
581
                return;
582
            }
583
            if (notification instanceof FeatureStoreNotification) {
584
                FeatureStoreNotification n = (FeatureStoreNotification) notification;
585
                switch (n.getType()) {
586
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
587
                        needrefresh = true;
588
                    case FeatureStoreNotification.AFTER_STARTEDITING:
589
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
590
                        updateButtonEnabledStatus();
591
                        break;
592
                }
593
            }
594
        }
595

    
596
        @Override
597
        public void dispose() {
598
            store.deleteObserver(this);
599
        }
600

    
601
    }
602

    
603
    @Override
604
    public void setQuery(FeatureQuery query) {
605
        if (this.features != null) {
606
            if (this.formset != null && !formset.isReadOnly() && this.formset.isAutosave() && this.formset.countValues() > 0) {
607
                if(this.formset.getForm().isModified()){
608
                    if (!store.isEditing()) {
609
                        try {
610
                            store.edit();
611
                        } catch (DataException e1) {
612
                            throw new RuntimeException("Can't set query", e1);
613
                        }
614
                    }
615
                    saveChanges(this.formset);
616
                }
617
            }
618
        }
619
        this.currentQuery = query;
620
        updateForm();
621
    }
622

    
623
    private FeatureQuery getCurrentQuery() {
624
        return this.currentQuery;
625
    }
626

    
627
    @Override
628
    public void showForm(MODE mode) {
629
        WindowManager winmgr = ToolsSwingLocator.getWindowManager();
630
        String title = this.definition.getLabel();
631
        winmgr.showWindow(this.asJComponent(), title, mode);
632
    }
633

    
634
    private void saveChanges(JDynFormSet theFormSet) {
635
        I18nManager i18n = ToolsLocator.getI18nManager();
636
        try {
637
            if (theFormSet.isInNewState()) {
638
                EditableFeature newFeature = store.createNewFeature(false);
639
                JDynForm form = formset.getForm();
640
                for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
641
                    String name = attr.getName();
642
                    if( !newFeature.canSetValue(name) ) {
643
                        continue;
644
                    }
645
                    JDynFormField field = form.getField(name);
646
                    if( field==null ) {
647
                        // The attribute is not in form, set default value
648
                        newFeature.set(name, attr.getDefaultValueCoerced());
649
                    } else {
650
                        try {
651
                            Object value = field.getValue();
652
                            newFeature.set(name, value);
653
                        } catch (Exception ex) {
654
                            LOGGER.warn("Can't get value of field '" + name + "'.", ex);
655
                        }
656
                    }
657
                }
658
                features.insert(newFeature);
659
                this.formset.message(i18n.getTranslation("_Record_saved"));
660
                try {
661
                    this.formset.setValues(features.asListOfDynObjects());
662
                    this.formset.setCurrentIndex((int) (features.getTotalSize()) - 1);
663
                } catch (Exception ex) {
664
                    LOGGER.warn("Can't reload form data after insert.", ex);
665
                }
666
            } else {
667
                int index = theFormSet.getCurrentIndex();
668
                DynObject currentElement = theFormSet.get(index);
669
                theFormSet.getFormValues(currentElement);
670
                features.update(((FacadeOfAFeature) currentElement).getEditableFeature());
671
                this.formset.message(i18n.getTranslation("_Record_saved"));
672
                try {
673
                    this.formset.setCurrentIndex(index);
674
                } catch (Exception ex) {
675
                    LOGGER.warn("Can't reload form data after insert.", ex);
676
                }
677
            }
678
        } catch (Exception ex) {
679
            theFormSet.message(i18n.getTranslation("error_saving_data_will_not_save"));
680
            throw new RuntimeException("Can't save values", ex);
681

    
682
        } finally {
683
            updateButtonEnabledStatus();
684
        }
685

    
686
    }
687

    
688
    private void deleteCurrentElement(JDynFormSet theFormSet) {
689
        I18nManager i18n = ToolsLocator.getI18nManager();
690
        try {
691
            int index = theFormSet.getCurrentIndex();
692
            DynObject currentElement = theFormSet.get(index);
693
            theFormSet.getFormValues(currentElement);
694
            Feature feature = ((FacadeOfAFeature) currentElement).getFeature();
695
            if (feature instanceof EditableFeature) {
696
                feature = ((EditableFeature) feature).getNotEditableCopy();
697
            }
698
            features.delete(feature);
699

    
700
            this.formset.message(i18n.getTranslation("_Record_removed"));
701

    
702
            this.formset.setValues(features.asListOfDynObjects());
703
            if (features.getTotalSize() - 1 < index) {
704
                index = index - 1;
705
            }
706
            this.formset.setCurrentIndex(index);
707

    
708
        } catch (Exception ex) {
709
            theFormSet.message(i18n.getTranslation("error_removing_data_will_not_remove"));
710
            throw new RuntimeException("Can't remove values", ex);
711

    
712
        } finally {
713
            updateButtonEnabledStatus();
714
        }
715

    
716
    }
717

    
718
    @Override
719
    public void saveChanges() {
720
        if (this.formset != null && this.formset.countValues() > 0) {
721
            if (store != null && !store.isEditing()) {
722
                try {
723
                    store.edit();
724
                } catch (DataException e1) {
725
                    LOGGER.warn("Can't edit the store " + store.getName());
726
                    throw new RuntimeException("Can't save changes.", e1);
727
                }
728
            }
729
            this.saveChanges(this.formset);
730
        }
731
    }
732

    
733
    private void updateButtonEnabledStatus() {
734
        if (this.formset == null) {
735
            return;
736
        }
737
        if (this.store == null || store.isBroken() || store.isAppending() || this.features == null) {
738
            this.formset.setReadOnly(true);
739
            formset.setActionVisible(STARTEDITING_ACTION, true);
740
            formset.setActionEnabled(STARTEDITING_ACTION, true);
741
            formset.setActionVisible(FINISHEDITING_ACTION, false);
742
            formset.setActionEnabled(FINISHEDITING_ACTION, false);
743
            formset.setActionEnabled(ACTION_DELETE, false);
744
            formset.setActionEnabled(ACTION_NEW, false);
745
            formset.setActionEnabled(ACTION_CANCEL_NEW, false);
746
            formset.setActionEnabled(ACTION_SAVE, false);
747
            formset.setActionEnabled(ACTION_SEARCH, false);
748
            formset.setActionEnabled(REFRESHFORM_ACTION, true);
749
            formset.setActionEnabled(ACTION_NAVIGATION, false);
750
            return;
751
        }
752
        if (this.needrefresh ) {
753
            this.formset.setReadOnly(true);
754
//            formset.setActionEnabled(STARTEDITING_ACTION, false);
755
//            formset.setActionEnabled(FINISHEDITING_ACTION, false);
756
            formset.setActionEnabled(ACTION_DELETE, false);
757
            formset.setActionEnabled(ACTION_NEW, false);
758
            formset.setActionEnabled(ACTION_CANCEL_NEW, false);
759
            formset.setActionEnabled(ACTION_SAVE, false);
760
            formset.setActionEnabled(ACTION_SEARCH, false);
761
            formset.setActionEnabled(ACTION_NAVIGATION, false);
762
            for (Action action : formset.getActions()) {
763
                formset.setActionEnabled((String) action.getValue(ACTION_COMMAND_KEY), false);
764
            }
765
            formset.setActionEnabled(REFRESHFORM_ACTION, true);
766
            return;
767
        }
768
        if (store.isEditing()) {
769
            this.formset.setReadOnly(false);
770
            formset.setActionVisible(STARTEDITING_ACTION, false);
771
            formset.setActionEnabled(STARTEDITING_ACTION, false);
772
            formset.setActionVisible(FINISHEDITING_ACTION, true);
773
            formset.setActionEnabled(FINISHEDITING_ACTION, true);
774
            if (formset.isInNewState()) {
775
                formset.setActionEnabled(ACTION_DELETE, false);
776
                formset.setActionEnabled(ACTION_SEARCH, false);
777
                formset.setActionEnabled(ACTION_NEW, false);
778
                formset.setActionEnabled(ACTION_CANCEL_NEW, true);
779
                formset.setActionEnabled(ACTION_SAVE, true);
780
                formset.setActionEnabled(FINISHEDITING_ACTION, false);
781
                formset.setActionEnabled(REFRESHFORM_ACTION, false);
782
//                setEnabledUniqueFields(true);
783

    
784
            } else if (this.features != null && this.features.isEmpty()) {
785
                formset.getForm().setReadOnly(true);
786
                formset.setActionEnabled(ACTION_DELETE, false);
787
                formset.setActionEnabled(ACTION_SEARCH, false);
788
                formset.setActionEnabled(ACTION_NEW, true);
789
                formset.setActionEnabled(ACTION_CANCEL_NEW, true);
790
                formset.setActionEnabled(ACTION_SAVE, false);
791
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
792
                formset.setActionEnabled(FINISHEDITING_ACTION, true);         
793
                formset.setActionEnabled(ACTION_NAVIGATION, false);
794

    
795
            } else if (formset.getForm().isModified()) {
796
                formset.setActionEnabled(ACTION_DELETE, false);
797
                formset.setActionEnabled(ACTION_SEARCH, false);
798
                formset.setActionEnabled(ACTION_NEW, false);
799
                formset.setActionEnabled(ACTION_CANCEL_NEW, false);
800
                formset.setActionEnabled(ACTION_SAVE, true);
801
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
802
                formset.setActionEnabled(FINISHEDITING_ACTION, false);
803
                formset.setActionEnabled(ACTION_NAVIGATION, false);
804

    
805
            } else {
806
                formset.setActionEnabled(ACTION_DELETE, true);
807
                formset.setActionEnabled(ACTION_SEARCH, true);
808
                formset.setActionEnabled(ACTION_NEW, true);
809
                formset.setActionEnabled(ACTION_CANCEL_NEW, false);
810
                formset.setActionEnabled(ACTION_SAVE, false);
811
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
812
                formset.setActionEnabled(FINISHEDITING_ACTION, true);
813
                formset.setActionEnabled(ACTION_NAVIGATION, true);
814
            }
815

    
816
            return;
817
        }
818
        this.formset.setReadOnly(true);
819
        formset.setActionVisible(STARTEDITING_ACTION, true);
820
        formset.setActionEnabled(STARTEDITING_ACTION, true);
821
        formset.setActionVisible(FINISHEDITING_ACTION, false);
822
        formset.setActionEnabled(FINISHEDITING_ACTION, false);
823
        formset.setActionEnabled(ACTION_DELETE, false);
824
        formset.setActionEnabled(ACTION_NEW, false);
825
        formset.setActionEnabled(ACTION_CANCEL_NEW, false);
826
        formset.setActionEnabled(ACTION_SAVE, false);
827
        formset.setActionEnabled(ACTION_SEARCH, true);
828
        formset.setActionEnabled(REFRESHFORM_ACTION, true);
829
    }
830

    
831
    private void clearUniqueFields() {
832
        for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
833
            if ((attr.isPrimaryKey() && !attr.isAutomatic()) || (attr.isIndexed() && !attr.allowIndexDuplicateds())) {
834
                JDynFormField field = formset.getForm().getField(attr.getName());
835
                if (field != null) {
836
                    field.clear();
837
                }
838
            }
839
        }
840
    }
841

    
842
    private void setEnabledUniqueFields(boolean enabled) {
843
        for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
844
            if ((attr.isPrimaryKey() && !attr.isAutomatic()) || (attr.isIndexed() && !attr.allowIndexDuplicateds())) {
845
                JDynFormField field = formset.getForm().getField(attr.getName());
846
                if (field != null) {
847
                    field.setReadOnly(!enabled);
848
                }
849
            }
850
        }
851
    }
852

    
853
    @Override
854
    public long getDataSetSize() {
855
        if (this.features != null) {
856
            return features.getTotalSize();
857
        }
858
        return 0;
859
    }
860

    
861
    @Override
862
    public FeatureStore getFeatureStore() {
863
        return this.store;
864
    }
865

    
866
    private class FormSetListener implements JDynFormSetListener {
867

    
868
        @Override
869
        public void formMessage(String message) {
870
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formMessage"));
871
        }
872

    
873
        @Override
874
        public void formClose() {
875
            panel.setVisible(false);
876
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formClose"));
877
        }
878

    
879
        @Override
880
        public void formMovedTo(int currentPosition) throws AbortActionException {
881
            LOGGER.trace("formMovedTo " + currentPosition);
882
            updateButtonEnabledStatus();
883
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formMovedTo"));
884
        }
885

    
886
        @Override
887
        public void formBeforeSave(JDynFormSet dynformSet) throws AbortActionException {
888
            LOGGER.trace("formBeforeSave");
889
            saveChanges(dynformSet);
890
            updateButtonEnabledStatus();
891
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeSave"));
892
        }
893

    
894
        @Override
895
        public void formBeforeNew(JDynFormSet dynformSet) throws AbortActionException {
896
            LOGGER.trace("formBeforeNew");
897
            clearUniqueFields();
898
            updateButtonEnabledStatus();
899
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeNew"));
900
        }
901

    
902
        @Override
903
        public void formBeforeDelete(JDynFormSet dynformSet) throws AbortActionException {
904
            LOGGER.trace("formBeforeDelete");
905
            updateButtonEnabledStatus();
906
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeDelete"));
907
        }
908

    
909
        @Override
910
        public void formAfterSave(JDynFormSet dynformSet) throws AbortActionException {
911
            LOGGER.trace("formAfterSave");
912
            updateButtonEnabledStatus();
913
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterSave"));
914
        }
915

    
916
        @Override
917
        public void formAfterNew(JDynFormSet dynformSet) throws AbortActionException {
918
            LOGGER.trace("formAfterNew");
919
            updateButtonEnabledStatus();
920
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterNew"));
921
        }
922

    
923
        @Override
924
        public void formAfterDelete(JDynFormSet dynformSet) throws AbortActionException {
925
            LOGGER.trace("formAfterDelete");
926
            deleteCurrentElement(dynformSet);
927
            updateButtonEnabledStatus();
928
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterDelete"));
929
        }
930

    
931
//        @Override
932
//        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
933
//            LOGGER.trace("formBeforeSearch");
934
//            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
935
//            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
936
//
937
//            JExpressionBuilder builder = dataSwingmanager.createQueryFilterExpresion(store);
938
//            FeatureQuery currentQuery = getCurrentQuery();
939
//            if( currentQuery!=null ) {
940
//                Evaluator filter = currentQuery.getFilter();
941
//                if( filter instanceof ExpressionEvaluator ) {
942
//                    Expression expression = ((ExpressionEvaluator)filter).getExpression();
943
//                    builder.setExpression(expression);
944
//                }
945
//            }
946
//            Dialog dialog = winmgr.createDialog(
947
//                    builder.asJComponent(),
948
//                    "Filtro",
949
//                    "Creacion de filtro sobre '"+store.getName()+"'",
950
//                    WindowManager_v2.BUTTONS_OK_CANCEL
951
//            );
952
//            dialog.show(WindowManager.MODE.DIALOG);
953
//            if( dialog.getAction() == WindowManager_v2.BUTTON_OK ) {
954
//                Expression expresion = builder.getExpression();
955
//                try {
956
//                    FeatureQuery query = store.createFeatureQuery();
957
//                    if( ExpressionUtils.isPhraseEmpty(expresion) ) {
958
//                        query.clearFilter();
959
//                    } else {
960
//                        query.setFilter(expresion);
961
//                    }
962
//                    setQuery(query);
963
//                } catch (Exception ex) {
964
//                    LOGGER.warn("Can't apply filter '" + expresion + "'.", ex);
965
//                }
966
//            }
967
//        }
968
        @Override
969
        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
970
            LOGGER.trace("formBeforeSearch");
971
            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
972
            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
973

    
974
            final FeatureStoreSearchPanel searchPanel = dataSwingmanager.createFeatureStoreSearchPanel(store);
975
            searchPanel.setShowActions(false);
976
            FeatureQuery currentQuery = getCurrentQuery();
977
            if (currentQuery != null) {
978
                Evaluator filter = currentQuery.getFilter();
979
                if (filter instanceof ExpressionEvaluator) {
980
                    Expression expression = ((ExpressionEvaluator) filter).toExpression();
981
                    searchPanel.setFilter(expression);
982
                    searchPanel.search();
983
                }
984
            }
985
            searchPanel.asJComponent().setPreferredSize(
986
                    new Dimension(FeatureStoreSearchPanel.DEFAULT_WIDTH, 320)
987
            );
988
            I18nManager i18n = ToolsLocator.getI18nManager();
989
            Dialog dialog = winmgr.createDialog(
990
                    searchPanel.asJComponent(),
991
                    i18n.getTranslation("_Filter"),
992
                    i18n.getTranslation("_Creating_filter_for") + ": '" + store.getName() + "'",
993
                    WindowManager_v2.BUTTONS_OK_CANCEL
994
            );
995
            dialog.show(WindowManager.MODE.DIALOG);
996
            if (dialog.getAction() == WindowManager_v2.BUTTON_OK) {
997
                SearchParameters params = searchPanel.fetch(null);
998
                if (params.getQuery() != null) {
999
                    FeatureQuery searchQuery = params.getQuery().getCopy();
1000

    
1001
                    Expression expresion = null;
1002
                    if (searchQuery != null) {
1003
                        expresion = searchQuery.getExpressionFilter();
1004
                    }
1005
                    try {
1006
                        FeatureQuery query = store.createFeatureQuery();
1007
                        if (ExpressionUtils.isPhraseEmpty(expresion)) {
1008
                            query.clearFilter();
1009
                        } else {
1010
                            query.setFilter(expresion);
1011
                        }
1012
                        setQuery(query);
1013
                    } catch (Exception ex) {
1014
                        LOGGER.warn("Can't apply filter '" + expresion + "'.", ex);
1015
                    }
1016
                } else {
1017
                    LOGGER.warn("FeatureQuery from parameters is null. Query is not applied to the JFeaturesFrom");
1018
                }
1019
            }
1020
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeSearch"));
1021
        }
1022

    
1023
        @Override
1024
        public void formAfterSearch(JDynFormSet dynformSet) throws AbortActionException {
1025
            LOGGER.trace("formAfterSearch");
1026
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterSearch"));
1027
        }
1028

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

    
1036
        @Override
1037
        public void formAfterCancelNew(JDynFormSet dynformSet) throws AbortActionException {
1038
            LOGGER.trace("formAfterCancelNew");
1039
            try {
1040
                int index = formset.getCurrentIndex();
1041
                if( index<0 ) {
1042
                    formset.getForm().clear();
1043
                } else {
1044
                    formset.setCurrentIndex(index);
1045
                }
1046
            } catch (Exception ex) {
1047
                LOGGER.warn("Can't reload form data after cancel new.", ex);
1048
            }            
1049
            updateButtonEnabledStatus();
1050
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterCancelNew"));
1051
        }
1052
    }
1053

    
1054
//    private static class StoreEditException extends AbortActionException {
1055
//
1056
//        /**
1057
//         *
1058
//         */
1059
//        private static final long serialVersionUID = -7682017811778577130L;
1060
//
1061
//        public StoreEditException(Throwable cause, String storename) {
1062
//            super("Can't edit the store '%(storename)'", cause, "cant_edit_the store_XstorenameX", serialVersionUID);
1063
//            setValue("storename", storename);
1064
//        }
1065
//    }
1066
    @Override
1067
    public void addActionListener(ActionListener listener) {
1068
        this.actionListeners.addActionListener(listener);
1069
    }
1070

    
1071
    @Override
1072
    public ActionListener[] getActionListeners() {
1073
        return this.actionListeners.getActionListeners();
1074
    }
1075

    
1076
    @Override
1077
    public void removeActionListener(ActionListener listener) {
1078
        this.actionListeners.removeActionListener(listener);
1079
    }
1080

    
1081
    @Override
1082
    public void removeAllActionListener() {
1083
        this.actionListeners.removeAllActionListener();
1084
    }
1085

    
1086
    @Override
1087
    public void fireActionEvent(ActionEvent event) {
1088
        this.actionListeners.fireActionEvent(event);
1089
    }
1090

    
1091
    @Override
1092
    public boolean hasActionListeners() {
1093
        return this.actionListeners.hasActionListeners();
1094
    }
1095

    
1096
    @Override
1097
    public Feature getCurrentFeature() {
1098
        long index = getCurrentIndex();
1099
        if( index<0 ) {
1100
            return null;
1101
        }
1102
        Feature f = get(index);
1103
        try {
1104
            DynObject adapter = f.getAsDynObject();
1105
            this.getFormset().getForm().getValues(adapter);
1106
            f = ((FacadeOfAFeature)adapter).getFeature();
1107
            return f;
1108
        } catch(Exception ex) {
1109
            return f;
1110
        }
1111
    }
1112
}