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

History | View | Annotate | Download (42.8 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.FeatureType;
61
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
62
import org.gvsig.fmap.dal.swing.AbstractDALActionFactory.AbstractDALActionContext;
63
import org.gvsig.fmap.dal.swing.DALActionFactory;
64
import org.gvsig.fmap.dal.swing.DALSwingLocator;
65
import org.gvsig.fmap.dal.swing.DataSwingManager;
66
import org.gvsig.fmap.dal.swing.impl.DefaultDataSwingManager;
67
import org.gvsig.fmap.dal.swing.impl.actions.ShowFormAction.ShowFormActionFactory;
68
import org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel;
69
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
70
import org.gvsig.tools.ToolsLocator;
71
import org.gvsig.tools.dispose.Disposable;
72
import org.gvsig.tools.dispose.DisposeUtils;
73
import org.gvsig.tools.dynform.AbortActionException;
74
import org.gvsig.tools.dynform.DynFormDefinition;
75
import org.gvsig.tools.dynform.DynFormLocator;
76
import org.gvsig.tools.dynform.DynFormManager;
77
import org.gvsig.tools.dynform.JDynForm;
78
import org.gvsig.tools.dynform.JDynFormField;
79
import org.gvsig.tools.dynform.JDynFormSet;
80
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_CANCEL_NEW;
81
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_DELETE;
82
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_NAVIGATION;
83
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_NEW;
84
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_SAVE;
85
import static org.gvsig.tools.dynform.JDynFormSet.ACTION_SEARCH;
86
import org.gvsig.tools.dynform.JDynFormSet.JDynFormSetListener;
87
import org.gvsig.tools.dynobject.DynClass;
88
import org.gvsig.tools.dynobject.DynObject;
89
import org.gvsig.tools.evaluator.Evaluator;
90
import org.gvsig.tools.exception.BaseException;
91
import org.gvsig.tools.i18n.I18nManager;
92
import org.gvsig.tools.locator.ReferenceNotRegisteredException;
93
import org.gvsig.tools.observer.Observable;
94
import org.gvsig.tools.observer.Observer;
95
import org.gvsig.tools.script.Script;
96
import org.gvsig.tools.swing.api.ActionListenerSupport;
97
import org.gvsig.tools.swing.api.ToolsSwingLocator;
98
import org.gvsig.tools.swing.api.ToolsSwingUtils;
99
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
100
import org.gvsig.tools.swing.api.windowmanager.Dialog;
101
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
102
import org.gvsig.tools.swing.api.windowmanager.WindowManager.MODE;
103
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
104
import org.gvsig.tools.swing.icontheme.IconTheme;
105
import org.gvsig.tools.util.PropertiesSupport;
106
import org.gvsig.tools.util.PropertiesSupportHelper;
107
import org.slf4j.Logger;
108
import org.slf4j.LoggerFactory;
109

    
110
/**
111
 * @author fdiaz
112
 *
113
 */
114
@SuppressWarnings("UseSpecificCatch")
115
public class DefaultJFeaturesForm implements JFeaturesForm, Disposable {
116

    
117
    private final String STARTEDITING_ACTION = "startEditing";
118
    private final String FINISHEDITING_ACTION = "finishEditing";
119
    private final String REFRESHFORM_ACTION = "refreshForm";
120

    
121
    private class JFeaturesFormPanel extends JPanel implements PropertiesSupport {
122

    
123
        private final PropertiesSupport properties;
124
        
125
        private JFeaturesFormPanel(PropertiesSupport properties, BorderLayout layout) {
126
            super(layout);
127
            this.properties = properties;
128
        }
129

    
130
        @Override
131
        public Object getProperty(String name) {
132
            return this.properties.getProperty(name);
133
        }
134

    
135
        @Override
136
        public void setProperty(String name, Object value) {
137
            this.properties.setProperty(name, value);
138
        }
139

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

    
149
        public FormActionContext() {
150
            super(ACTION_CONTEXT_NAME);
151
        }
152

    
153
        @Override
154
        public DataStore getStore() {
155
            return store;
156
        }
157

    
158
        @Override
159
        public FeatureQuery getQuery() {
160
            return currentQuery;
161
        }
162

    
163
        @Override
164
        public int getSelectedsCount() {
165
            return 0;
166
        }
167

    
168
        @Override
169
        public Expression getFilterForSelecteds() {
170
            return null;
171
        }
172

    
173
        @Override
174
        public JComponent getActionButton(String actionName) {
175
            if (formset == null) {
176
                return null;
177
            }
178
            return formset.getActionButton(actionName);
179
        }
180

    
181
    }
182

    
183
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJFeaturesForm.class);
184

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

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

    
212
    public static void selfRegister() {
213
        IconTheme theme;
214
        try {
215
           theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
216
        } catch(ReferenceNotRegisteredException ex) {
217
            return;
218
        }
219
        String[][] iconNames = new String[][]{
220
            new String[]{"dalswing", "form-refresh-data"}
221
        };
222
        for (String[] icon : iconNames) {
223
            URL url = DefaultJFeaturesForm.class.getResource(icon[1] + ".png");
224
            theme.registerDefault("DALSwing", icon[0], icon[1], null, url);
225
        }
226

    
227
    }
228

    
229
    @Override
230
    public void setPreferredSize(Dimension dimension) {
231
        panel.setPreferredSize(dimension);
232
    }
233

    
234
    private void updateForm() {
235
        if (this.formset == null) {
236
            this.getFormset();
237
        }
238
        try {
239
            if (this.currentQuery != null) {
240
                this.currentQuery.retrievesAllAttributes();
241
            }
242
            this.features = DALLocator.getDataManager().createFeaturePagingHelper(store, this.currentQuery, PAGE_SIZE);
243
            callUserEvent("form_beforeReload", this.formset.getForm());
244
            this.formset.setValues(features.asListOfDynObjects());
245
            callUserEvent("form_afterReload", this.formset.getForm());
246
        } catch (Exception ex) {
247
            throw new RuntimeException("Can't update form", ex);
248
        }
249
        this.needrefresh = false;
250
        updateButtonEnabledStatus();
251
    }
252

    
253
    @Override
254
    public JComponent asJComponent() {
255
        if (this.features == null) {
256
            try {
257
                updateForm();
258
            } catch (Exception ex) {
259
                throw new RuntimeException(ex);
260
            }
261
        }
262
        return this.panel;
263
    }
264

    
265
    @Override
266
    public void bind(FeatureStore store) {
267
        this.bind(store, null, null);
268
    }
269

    
270
    public void bind(FeatureStore store, DynClass definition) {
271
        this.bind(store, definition, null);
272
    }
273

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

    
305
    @Override
306
    public void dispose() {
307
        if( this.formset!=null ) {
308
            Action action = this.formset.getAction(FINISHEDITING_ACTION);
309
            if( action!=null ) {
310
                DisposeUtils.disposeQuietly(action);
311
            }
312
            action = this.formset.getAction(STARTEDITING_ACTION);
313
            if( action!=null ) {
314
                DisposeUtils.disposeQuietly(action);
315
            }
316
        }
317
        if( this.panel!=null ) {
318
            this.panel.setVisible(false);
319
        }
320
        DisposeUtils.disposeQuietly(store);
321
        this.store = null;
322
        this.panel = null;
323
        this.formset = null;
324
        this.features = null;
325
        this.definition = null;
326
        this.currentQuery = null;
327
        this.otherActions = null;
328
    }
329

    
330
    public static class MyFeaturesFormContext extends DefaultFeaturesFormContext {
331

    
332
        private final DefaultJFeaturesForm featuresForm;
333
        
334
        public MyFeaturesFormContext(DefaultJFeaturesForm featuresForm) {
335
            super(featuresForm.store);
336
            this.featuresForm = featuresForm;
337
        }
338
        
339
        @Override
340
        public JFeaturesForm getFeaturesForm() {
341
            return this.featuresForm;
342
        }
343
        @Override
344
        public Feature getCurrentFeature() {    
345
            return this.featuresForm.getCurrentFeature();
346
        }
347
    }
348
    
349
    @Override
350
    public JDynFormSet getFormset() {
351
        if (this.formset == null) {
352
            DynFormManager formManager = DynFormLocator.getDynFormManager();
353
            this.formset = formManager.createJDynFormSet(
354
                    new MyFeaturesFormContext(this),
355
                    this.definition,
356
                    null
357
            );
358
            List<String> groups = this.definition.getGroups();
359
            if (groups.size() == 1 && groups.get(0) == null) {
360
                this.formset.setLayoutMode(JDynForm.USE_PLAIN);
361
            } else {
362
                this.formset.setLayoutMode(JDynForm.USE_TABS);
363
            }
364
            this.formset.setAllowNew(true);
365
            this.formset.setAllowDelete(true);
366
            this.formset.setAllowUpdate(true);
367
            this.formset.setAllowClose(true);
368
            this.formset.setAllowSearch(true);
369
            this.formset.setAutosave(true);
370

    
371
            this.formset.addAction(new StartEditingAction());
372
            this.formset.addAction(new FinishEditingAction());
373
            this.formset.addAction(new RefreshAction());
374

    
375
            FormActionContext actionContext = new FormActionContext();
376
            try {
377
                Collection<DALActionFactory> factories = DALSwingLocator.getSwingManager().getStoreActions();
378
                for (DALActionFactory factory : factories) {
379
                    if (factory == null || StringUtils.equalsIgnoreCase(factory.getName(), ShowFormActionFactory.ACTION_NAME)) {
380
                        continue;
381
                    }
382
                    try {
383
                        if (factory.isApplicable(actionContext)) {
384
                            Action action = factory.createAction(actionContext);
385
                            this.formset.addAction(action);
386
                        }
387
                    } catch (Exception ex) {
388
                        LOGGER.warn("Can't add action " + factory.getName(), ex);
389
                    }
390

    
391
                }
392
            } catch (Exception ex) {
393
                LOGGER.warn("Can't add actions", ex);
394
            }
395
            for (Action action : this.otherActions) {
396
                this.formset.addAction(action);
397
            }
398

    
399
            this.formset.addListener(new FormSetListener());
400
            this.formset.getForm().addListener(new JDynForm.JDynFormListener() {
401
                @Override
402
                public void message(String string) {
403
                }
404

    
405
                @Override
406
                public void fieldChanged(JDynFormField jdff) {
407
                    updateButtonEnabledStatus();
408
                }
409
            });
410

    
411
            ToolsSwingLocator.getToolsSwingManager().removeBorder(this.formset.asJComponent());
412
            this.panel.add(this.formset.asJComponent(), BorderLayout.CENTER);
413
            this.panel.revalidate();
414
            ToolsSwingUtils.ensureRowsCols(this.panel, 8, 70, 25, 100);
415

    
416
        }
417
        updateButtonEnabledStatus();
418
        return this.formset;
419
    }
420

    
421
    @Override
422
    public void addAction(Action action) {
423
        this.otherActions.add(action);
424
        if (this.formset != null) {
425
            this.formset.addAction(action);
426
        }
427
    }
428

    
429
    @Override
430
    public long getCurrentIndex() {
431
        if (this.formset == null) {
432
            return -1;
433
        }
434
        return this.formset.getCurrentIndex();
435
    }
436

    
437
    @Override
438
    public Feature get(long index) {
439
        if (this.formset == null || this.features == null) {
440
            return null;
441
        }
442
        try {
443
            return this.features.getFeatureAt(index);
444
        } catch (BaseException ex) {
445
            return null;
446
        }
447
    }
448

    
449
    private class RefreshAction extends AbstractAction {
450

    
451
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
452
        public RefreshAction() {
453
            I18nManager i18nManager = ToolsLocator.getI18nManager();
454
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
455

    
456
            this.putValue(NAME, null);
457
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Reload_data"));
458
            this.putValue(SMALL_ICON, iconTheme.get("form-refresh-data"));
459
            this.putValue(ACTION_COMMAND_KEY, REFRESHFORM_ACTION);
460
            this.setEnabled(!formset.isInNewState());
461
        }
462

    
463
        @Override
464
        public void actionPerformed(ActionEvent ae) {
465
            try {
466
                I18nManager i18n = ToolsLocator.getI18nManager();
467
                formset.message(i18n.getTranslation("_Form_reloaded"));
468
                int x=formset.getCurrentIndex();
469
                updateForm();
470
                formset.setCurrentIndex(x);
471
            } catch (Exception ex) {
472
                LOGGER.warn("Can't reload form", ex);
473
            }
474
        }
475
    }
476

    
477
    private class FinishEditingAction extends AbstractAction implements Observer, Disposable {
478

    
479
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
480
        public FinishEditingAction() {
481
            I18nManager i18nManager = ToolsLocator.getI18nManager();
482
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
483

    
484
            this.putValue(NAME, null);
485
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Stop_editing"));
486
            this.putValue(SMALL_ICON, iconTheme.get("table-stop-editing"));
487
            this.putValue(ACTION_COMMAND_KEY, FINISHEDITING_ACTION);
488

    
489
            this.setEnabled(store.isEditing());
490
            store.addObserver(this);
491
        }
492

    
493
        @Override
494
        public void actionPerformed(ActionEvent ae) {
495
            if (store == null || formset == null) {
496
                return;
497
            }
498
            if (store.isEditing()) {
499
                ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
500
                I18nManager i18nManager = ToolsLocator.getI18nManager();
501
                try {
502
                    int x = dialogManager.confirmDialog(
503
                            i18nManager.getTranslation("_Do_you_want_to_finish_editing_and_save_the_changes") + "\n\n"
504
                            + i18nManager.getTranslation("_Press_cancel_to_cancel_editing_and_changes"),
505
                            i18nManager.getTranslation("_Stop_editing"),
506
                            JOptionPane.YES_NO_CANCEL_OPTION,
507
                            JOptionPane.QUESTION_MESSAGE
508
                    );
509
                    switch (x) {
510
                        case JOptionPane.YES_OPTION:
511
                            store.finishEditing();
512
                            break;
513
                        case JOptionPane.NO_OPTION:
514
                            break;
515
                        case JOptionPane.CANCEL_OPTION:
516
                            store.cancelEditing();
517
                            int index = formset.getCurrentIndex();
518
                            try {
519
                                formset.setCurrentIndex(index);
520
                            } catch (Exception ex) {
521
                                LOGGER.warn("Can't reload form data after edit.", ex);
522
                            }
523
                            break;
524
                    }
525
                } catch (Exception ex) {
526
                    LOGGER.warn("Can't finish editing in FeatureForm (" + store.getName() + ").", ex);
527
                    dialogManager.messageDialog(
528
                            i18nManager.getTranslation("_Problems_finish_table_editing") + "\n\n"
529
                            + i18nManager.getTranslation("_see_error_log_for_more_information"),
530
                            i18nManager.getTranslation("_Stop_editing"),
531
                            JOptionPane.ERROR_MESSAGE
532
                    );
533
                }
534
            }
535
            updateButtonEnabledStatus();
536
        }
537

    
538
        @Override
539
        public void update(Observable observable, Object notification) {
540
            if (store == null || formset == null) {
541
                return;
542
            }
543
            if (notification instanceof FeatureStoreNotification) {
544
                FeatureStoreNotification n = (FeatureStoreNotification) notification;
545
                switch (n.getType()) {
546
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
547
                        needrefresh = true;
548
                    case FeatureStoreNotification.AFTER_STARTEDITING:
549
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
550
                        updateButtonEnabledStatus();
551
                        break;
552
                }
553
            }
554
        }
555

    
556
        @Override
557
        public void dispose() {
558
            store.deleteObserver(this);
559
        }
560

    
561
    }
562

    
563
    private class StartEditingAction extends AbstractAction implements Observer, Disposable {
564

    
565
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
566
        public StartEditingAction() {
567
            I18nManager i18nManager = ToolsLocator.getI18nManager();
568
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
569

    
570
            this.putValue(NAME, null);
571
            this.putValue(SHORT_DESCRIPTION, i18nManager.getTranslation("_Start_editing"));
572
            this.putValue(SMALL_ICON, iconTheme.get("table-start-editing"));
573
            this.putValue(ACTION_COMMAND_KEY, STARTEDITING_ACTION);
574

    
575
            this.setEnabled(!store.isEditing());
576
            store.addObserver(this);
577
        }
578

    
579
        @Override
580
        public void actionPerformed(ActionEvent ae) {
581
            if (store == null || formset == null) {
582
                return;
583
            }
584
            if (!store.isEditing()) {
585
                try {
586
                    store.edit();
587
                } catch (DataException ex) {
588
                    LOGGER.warn("Can't finish editing in FeatureForm (" + store.getName() + ").", ex);
589
                }
590
            }
591
            updateButtonEnabledStatus();
592
        }
593

    
594
        @Override
595
        public void update(Observable observable, Object notification) {
596
            if (store == null || formset == null) {
597
                return;
598
            }
599
            if (notification instanceof FeatureStoreNotification) {
600
                FeatureStoreNotification n = (FeatureStoreNotification) notification;
601
                switch (n.getType()) {
602
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
603
                        needrefresh = true;
604
                    case FeatureStoreNotification.AFTER_STARTEDITING:
605
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
606
                        updateButtonEnabledStatus();
607
                        break;
608
                }
609
            }
610
        }
611

    
612
        @Override
613
        public void dispose() {
614
            store.deleteObserver(this);
615
        }
616

    
617
    }
618

    
619
    @Override
620
    public void setQuery(FeatureQuery query) {
621
        if (this.features != null) {
622
            if (this.formset != null && !formset.isReadOnly() && this.formset.isAutosave() && this.formset.countValues() > 0) {
623
                if(this.formset.getForm().isModified()){
624
                    if (!store.isEditing()) {
625
                        try {
626
                            store.edit();
627
                        } catch (DataException e1) {
628
                            throw new RuntimeException("Can't set query", e1);
629
                        }
630
                    }
631
                    saveChanges(this.formset);
632
                }
633
            }
634
        }
635
        this.currentQuery = query;
636
        updateForm();
637
    }
638

    
639
    private FeatureQuery getCurrentQuery() {
640
        return this.currentQuery;
641
    }
642

    
643
    @Override
644
    public void showForm(MODE mode) {
645
        String title = this.definition.getLabel();
646
        showForm(title, mode);
647
    }
648

    
649
    public void showForm(String title, MODE mode) {
650
        WindowManager winmgr = ToolsSwingLocator.getWindowManager();
651
        if( StringUtils.isBlank(title) ) {
652
            title = this.definition.getLabel();
653
        }
654
        winmgr.showWindow(this.asJComponent(), title, mode);
655
    }
656
    
657
    public void hideForm() {
658
        DisposeUtils.dispose(this);
659
    }
660

    
661
    private void saveChanges(JDynFormSet theFormSet) {
662
        I18nManager i18n = ToolsLocator.getI18nManager();
663
        try {
664
            if (theFormSet.isInNewState()) {
665
                EditableFeature newFeature = store.createNewFeature(false);
666
                JDynForm form = formset.getForm();
667
                for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
668
                    String name = attr.getName();
669
                    if( !newFeature.canSetValue(name) ) {
670
                        continue;
671
                    }
672
                    JDynFormField field = form.getField(name);
673
                    if( field==null ) {
674
                        // The attribute is not in form, set default value
675
                        newFeature.set(name, attr.getDefaultValueCoerced());
676
                    } else {
677
                        try {
678
                            Object value = field.getValue();
679
                            newFeature.set(name, value);
680
                        } catch (Exception ex) {
681
                            LOGGER.warn("Can't get value of field '" + name + "'.", ex);
682
                        }
683
                    }
684
                }
685
                features.insert(newFeature);
686
                this.formset.message(i18n.getTranslation("_Record_saved"));
687
                try {
688
                    this.formset.setValues(features.asListOfDynObjects());
689
                    this.formset.setCurrentIndex((int) (features.getTotalSize()) - 1);
690
                } catch (Exception ex) {
691
                    LOGGER.warn("Can't reload form data after insert.", ex);
692
                }
693
            } else {
694
                int index = theFormSet.getCurrentIndex();
695
                DynObject currentElement = theFormSet.get(index);
696
                theFormSet.getFormValues(currentElement);
697
                features.update(((FacadeOfAFeature) currentElement).getEditableFeature());
698
                this.formset.message(i18n.getTranslation("_Record_saved"));
699
                try {
700
                    this.formset.setCurrentIndex(index);
701
                } catch (Exception ex) {
702
                    LOGGER.warn("Can't reload form data after insert.", ex);
703
                }
704
            }
705
        } catch (Exception ex) {
706
            theFormSet.message(i18n.getTranslation("error_saving_data_will_not_save"));
707
            throw new RuntimeException("Can't save values", ex);
708

    
709
        } finally {
710
            updateButtonEnabledStatus();
711
        }
712

    
713
    }
714

    
715
    private void deleteCurrentElement(JDynFormSet theFormSet) {
716
        I18nManager i18n = ToolsLocator.getI18nManager();
717
        try {
718
            int index = theFormSet.getCurrentIndex();
719
            DynObject currentElement = theFormSet.get(index);
720
            theFormSet.getFormValues(currentElement);
721
            Feature feature = ((FacadeOfAFeature) currentElement).getFeature();
722
            if (feature instanceof EditableFeature) {
723
                feature = ((EditableFeature) feature).getNotEditableCopy();
724
            }
725
            features.delete(feature);
726

    
727
            this.formset.message(i18n.getTranslation("_Record_removed"));
728

    
729
            this.formset.setValues(features.asListOfDynObjects());
730
            if (features.getTotalSize() - 1 < index) {
731
                index = index - 1;
732
            }
733
            this.formset.setCurrentIndex(index);
734

    
735
        } catch (Exception ex) {
736
            theFormSet.message(i18n.getTranslation("error_removing_data_will_not_remove"));
737
            throw new RuntimeException("Can't remove values", ex);
738

    
739
        } finally {
740
            updateButtonEnabledStatus();
741
        }
742

    
743
    }
744

    
745
    @Override
746
    public void saveChanges() {
747
        if (this.formset != null && this.formset.countValues() > 0) {
748
            if (store != null && !store.isEditing()) {
749
                try {
750
                    store.edit();
751
                } catch (DataException e1) {
752
                    LOGGER.warn("Can't edit the store " + store.getName());
753
                    throw new RuntimeException("Can't save changes.", e1);
754
                }
755
            }
756
            this.saveChanges(this.formset);
757
        }
758
    }
759

    
760
    private void updateButtonEnabledStatus() {
761
        if (this.formset == null) {
762
            return;
763
        }
764
        if (this.store == null || store.isBroken() || store.isAppending() || this.features == null) {
765
            this.formset.setReadOnly(true);
766
            formset.setActionVisible(STARTEDITING_ACTION, true);
767
            formset.setActionEnabled(STARTEDITING_ACTION, true);
768
            formset.setActionVisible(FINISHEDITING_ACTION, false);
769
            formset.setActionEnabled(FINISHEDITING_ACTION, false);
770
            formset.setActionEnabled(ACTION_DELETE, false);
771
            formset.setActionEnabled(ACTION_NEW, false);
772
            formset.setActionEnabled(ACTION_CANCEL_NEW, false);
773
            formset.setActionEnabled(ACTION_SAVE, false);
774
            formset.setActionEnabled(ACTION_SEARCH, false);
775
            formset.setActionEnabled(REFRESHFORM_ACTION, true);
776
            formset.setActionEnabled(ACTION_NAVIGATION, false);
777
            return;
778
        }
779
        if (this.needrefresh ) {
780
            this.formset.setReadOnly(true);
781
//            formset.setActionEnabled(STARTEDITING_ACTION, false);
782
//            formset.setActionEnabled(FINISHEDITING_ACTION, false);
783
            formset.setActionEnabled(ACTION_DELETE, false);
784
            formset.setActionEnabled(ACTION_NEW, false);
785
            formset.setActionEnabled(ACTION_CANCEL_NEW, false);
786
            formset.setActionEnabled(ACTION_SAVE, false);
787
            formset.setActionEnabled(ACTION_SEARCH, false);
788
            formset.setActionEnabled(ACTION_NAVIGATION, false);
789
            for (Action action : formset.getActions()) {
790
                formset.setActionEnabled((String) action.getValue(ACTION_COMMAND_KEY), false);
791
            }
792
            formset.setActionEnabled(REFRESHFORM_ACTION, true);
793
            return;
794
        }
795
        if (store.isEditing()) {
796
            this.formset.setReadOnly(false);
797
            formset.setActionVisible(STARTEDITING_ACTION, false);
798
            formset.setActionEnabled(STARTEDITING_ACTION, false);
799
            formset.setActionVisible(FINISHEDITING_ACTION, true);
800
            formset.setActionEnabled(FINISHEDITING_ACTION, true);
801
            if (formset.isInNewState()) {
802
                formset.setActionEnabled(ACTION_DELETE, false);
803
                formset.setActionEnabled(ACTION_SEARCH, false);
804
                formset.setActionEnabled(ACTION_NEW, false);
805
                formset.setActionEnabled(ACTION_CANCEL_NEW, true);
806
                formset.setActionEnabled(ACTION_SAVE, true);
807
                formset.setActionEnabled(FINISHEDITING_ACTION, false);
808
                formset.setActionEnabled(REFRESHFORM_ACTION, false);
809
//                setEnabledUniqueFields(true);
810

    
811
            } else if (this.features != null && this.features.isEmpty()) {
812
                formset.getForm().setReadOnly(true);
813
                formset.setActionEnabled(ACTION_DELETE, false);
814
                formset.setActionEnabled(ACTION_SEARCH, false);
815
                formset.setActionEnabled(ACTION_NEW, true);
816
                formset.setActionEnabled(ACTION_CANCEL_NEW, true);
817
                formset.setActionEnabled(ACTION_SAVE, false);
818
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
819
                formset.setActionEnabled(FINISHEDITING_ACTION, true);         
820
                formset.setActionEnabled(ACTION_NAVIGATION, false);
821

    
822
            } else if (formset.getForm().isModified()) {
823
                formset.setActionEnabled(ACTION_DELETE, false);
824
                formset.setActionEnabled(ACTION_SEARCH, false);
825
                formset.setActionEnabled(ACTION_NEW, false);
826
                formset.setActionEnabled(ACTION_CANCEL_NEW, false);
827
                formset.setActionEnabled(ACTION_SAVE, true);
828
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
829
                formset.setActionEnabled(FINISHEDITING_ACTION, false);
830
                formset.setActionEnabled(ACTION_NAVIGATION, false);
831

    
832
            } else {
833
                formset.setActionEnabled(ACTION_DELETE, true);
834
                formset.setActionEnabled(ACTION_SEARCH, true);
835
                formset.setActionEnabled(ACTION_NEW, true);
836
                formset.setActionEnabled(ACTION_CANCEL_NEW, false);
837
                formset.setActionEnabled(ACTION_SAVE, false);
838
                formset.setActionEnabled(REFRESHFORM_ACTION, true);
839
                formset.setActionEnabled(FINISHEDITING_ACTION, true);
840
                formset.setActionEnabled(ACTION_NAVIGATION, true);
841
            }
842

    
843
            return;
844
        }
845
        this.formset.setReadOnly(true);
846
        formset.setActionVisible(STARTEDITING_ACTION, true);
847
        formset.setActionEnabled(STARTEDITING_ACTION, true);
848
        formset.setActionVisible(FINISHEDITING_ACTION, false);
849
        formset.setActionEnabled(FINISHEDITING_ACTION, false);
850
        formset.setActionEnabled(ACTION_DELETE, false);
851
        formset.setActionEnabled(ACTION_NEW, false);
852
        formset.setActionEnabled(ACTION_CANCEL_NEW, false);
853
        formset.setActionEnabled(ACTION_SAVE, false);
854
        formset.setActionEnabled(ACTION_SEARCH, true);
855
        formset.setActionEnabled(REFRESHFORM_ACTION, true);
856
    }
857

    
858
    private void clearUniqueFields() {
859
        for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
860
            if ((attr.isPrimaryKey() && !attr.isAutomatic()) || (attr.isIndexed() && !attr.allowIndexDuplicateds())) {
861
                JDynFormField field = formset.getForm().getField(attr.getName());
862
                if (field != null) {
863
                    field.clear();
864
                }
865
            }
866
        }
867
    }
868

    
869
    private void setEnabledUniqueFields(boolean enabled) {
870
        for (FeatureAttributeDescriptor attr : this.store.getDefaultFeatureTypeQuietly()) {
871
            if ((attr.isPrimaryKey() && !attr.isAutomatic()) || (attr.isIndexed() && !attr.allowIndexDuplicateds())) {
872
                JDynFormField field = formset.getForm().getField(attr.getName());
873
                if (field != null) {
874
                    field.setReadOnly(!enabled);
875
                }
876
            }
877
        }
878
    }
879

    
880
    @Override
881
    public long getDataSetSize() {
882
        if (this.features != null) {
883
            return features.getTotalSize();
884
        }
885
        return 0;
886
    }
887

    
888
    @Override
889
    public FeatureStore getFeatureStore() {
890
        return this.store;
891
    }
892
    
893
    public FeatureType getFeatureType() {
894
        if( this.store == null ) {
895
            return null;
896
        }
897
        return this.store.getDefaultFeatureTypeQuietly();
898
    }
899

    
900
    private class FormSetListener implements JDynFormSetListener {
901

    
902
        @Override
903
        public void formMessage(String message) {
904
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formMessage"));
905
        }
906

    
907
        @Override
908
        public void formClose() {
909
            panel.setVisible(false);
910
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formClose"));
911
        }
912

    
913
        @Override
914
        public void formMovedTo(int currentPosition) throws AbortActionException {
915
            LOGGER.trace("formMovedTo " + currentPosition);
916
            updateButtonEnabledStatus();
917
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formMovedTo"));
918
        }
919

    
920
        @Override
921
        public void formBeforeSave(JDynFormSet dynformSet) throws AbortActionException {
922
            LOGGER.trace("formBeforeSave");
923
            saveChanges(dynformSet);
924
            updateButtonEnabledStatus();
925
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeSave"));
926
        }
927

    
928
        @Override
929
        public void formBeforeNew(JDynFormSet dynformSet) throws AbortActionException {
930
            LOGGER.trace("formBeforeNew");
931
            clearUniqueFields();
932
            updateButtonEnabledStatus();
933
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeNew"));
934
        }
935

    
936
        @Override
937
        public void formBeforeDelete(JDynFormSet dynformSet) throws AbortActionException {
938
            LOGGER.trace("formBeforeDelete");
939
            updateButtonEnabledStatus();
940
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formBeforeDelete"));
941
        }
942

    
943
        @Override
944
        public void formAfterSave(JDynFormSet dynformSet) throws AbortActionException {
945
            LOGGER.trace("formAfterSave");
946
            updateButtonEnabledStatus();
947
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterSave"));
948
        }
949

    
950
        @Override
951
        public void formAfterNew(JDynFormSet dynformSet) throws AbortActionException {
952
            LOGGER.trace("formAfterNew");
953
            updateButtonEnabledStatus();
954
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterNew"));
955
        }
956

    
957
        @Override
958
        public void formAfterDelete(JDynFormSet dynformSet) throws AbortActionException {
959
            LOGGER.trace("formAfterDelete");
960
            deleteCurrentElement(dynformSet);
961
            updateButtonEnabledStatus();
962
            actionListeners.fireActionEvent(new ActionEvent(this, 1, "formAfterDelete"));
963
        }
964

    
965
        @Override
966
        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
967
            LOGGER.trace("formBeforeSearch");
968
            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
969
            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
970

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

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

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

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

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

    
1051
    @Override
1052
    public void addActionListener(ActionListener listener) {
1053
        this.actionListeners.addActionListener(listener);
1054
    }
1055

    
1056
    @Override
1057
    public ActionListener[] getActionListeners() {
1058
        return this.actionListeners.getActionListeners();
1059
    }
1060

    
1061
    @Override
1062
    public void removeActionListener(ActionListener listener) {
1063
        this.actionListeners.removeActionListener(listener);
1064
    }
1065

    
1066
    @Override
1067
    public void removeAllActionListener() {
1068
        this.actionListeners.removeAllActionListener();
1069
    }
1070

    
1071
    @Override
1072
    public void fireActionEvent(ActionEvent event) {
1073
        this.actionListeners.fireActionEvent(event);
1074
    }
1075

    
1076
    @Override
1077
    public boolean hasActionListeners() {
1078
        return this.actionListeners.hasActionListeners();
1079
    }
1080

    
1081
    @Override
1082
    public Feature getCurrentFeature() {
1083
        long index = getCurrentIndex();
1084
        if( index<0 ) {
1085
            return null;
1086
        }
1087
        Feature f = get(index);
1088
        try {
1089
            DynObject adapter = f.getAsDynObject();
1090
            this.getFormset().getForm().getValues(adapter);
1091
            f = ((FacadeOfAFeature)adapter).getFeature();
1092
            return f;
1093
        } catch(Exception ex) {
1094
            return f;
1095
        }
1096
    }
1097

    
1098
    protected void callUserEvent(String name, Object...args) {
1099
//        try {
1100
            JDynForm form = this.formset.getForm();
1101
            form.callUserEvent(name, args);
1102
//        } catch(NoSuchMethodException ex) {
1103
//            LOGGER.debug("Function '"+name+"' not found.", ex);
1104
//            // Do nothing
1105
//        } catch(Exception ex) {
1106
//            LOGGER.warn("Error calling form event '"+name+"'.", ex);
1107
//        }
1108
    }
1109
}