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

History | View | Annotate | Download (21.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.util.ArrayList;
29
import java.util.List;
30
import javax.swing.AbstractAction;
31
import javax.swing.Action;
32
import static javax.swing.Action.ACTION_COMMAND_KEY;
33
import static javax.swing.Action.NAME;
34
import static javax.swing.Action.SHORT_DESCRIPTION;
35
import static javax.swing.Action.SMALL_ICON;
36

    
37
import javax.swing.JComponent;
38
import javax.swing.JOptionPane;
39
import javax.swing.JPanel;
40
import org.gvsig.expressionevaluator.Expression;
41
import org.gvsig.expressionevaluator.ExpressionUtils;
42
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
43

    
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

    
47
import org.gvsig.featureform.swing.JFeaturesForm;
48
import org.gvsig.fmap.dal.DALLocator;
49
import org.gvsig.fmap.dal.exception.DataException;
50
import org.gvsig.fmap.dal.expressionevaluator.ExpressionEvaluator;
51
import org.gvsig.fmap.dal.feature.Feature;
52
import org.gvsig.fmap.dal.feature.FacadeOfAFeature;
53
import org.gvsig.fmap.dal.feature.FeatureQuery;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
56
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
57
import org.gvsig.fmap.dal.swing.DALSwingLocator;
58
import org.gvsig.fmap.dal.swing.DataSwingManager;
59
import org.gvsig.fmap.dal.swing.impl.DefaultDataSwingManager;
60
import org.gvsig.tools.ToolsLocator;
61
import org.gvsig.tools.dynform.AbortActionException;
62
import org.gvsig.tools.dynform.DynFormDefinition;
63
import org.gvsig.tools.dynform.DynFormLocator;
64
import org.gvsig.tools.dynform.DynFormManager;
65
import org.gvsig.tools.dynform.JDynForm;
66
import org.gvsig.tools.dynform.JDynFormSet;
67
import org.gvsig.tools.dynform.JDynFormSet.JDynFormSetListener;
68
import org.gvsig.tools.dynobject.DynClass;
69
import org.gvsig.tools.dynobject.DynObject;
70
import org.gvsig.tools.evaluator.Evaluator;
71
import org.gvsig.tools.exception.BaseException;
72
import org.gvsig.tools.i18n.I18nManager;
73
import org.gvsig.tools.observer.Observable;
74
import org.gvsig.tools.observer.Observer;
75
import org.gvsig.tools.service.ServiceException;
76
import org.gvsig.tools.swing.api.ToolsSwingLocator;
77
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
78
import org.gvsig.tools.swing.api.windowmanager.Dialog;
79
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
80
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
81
import org.gvsig.tools.swing.api.windowmanager.WindowManager.MODE;
82
import org.gvsig.tools.swing.icontheme.IconTheme;
83

    
84
/**
85
 * @author fdiaz
86
 *
87
 */
88
@SuppressWarnings("UseSpecificCatch")
89
public class DefaultJFeaturesForm implements JFeaturesForm {
90

    
91
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJFeaturesForm.class);
92

    
93
    private static final int PAGE_SIZE = 500;
94
    private final JPanel panel;
95
    private JDynFormSet formset;
96
    private FeatureStore store;
97
    private FeaturePagingHelper ph;
98
    private DynFormDefinition definition = null;
99
    private FeatureQuery currentQuery;
100
    private final List<Action> otherActions;
101

    
102
    public DefaultJFeaturesForm() {
103
        this.panel = new JPanel(new BorderLayout());
104
        this.otherActions = new ArrayList<>();
105
    }
106

    
107
    @Override
108
    public void setPreferredSize(Dimension dimension) {
109
        panel.setPreferredSize(dimension);
110
    }
111

    
112
    private void updateForm() {
113
        if (this.formset == null) {
114
            this.panel.add(this.getFormset().asJComponent(), BorderLayout.CENTER);
115
        }
116
        try {
117
            this.ph = DALLocator.getDataManager().createFeaturePagingHelper(store, this.currentQuery, PAGE_SIZE);
118
            this.formset.setValues(ph.asListOfDynObjects());
119
        } catch (Exception ex) {
120
            throw new RuntimeException("Can't update form", ex);
121
        }
122
    }
123

    
124
    @Override
125
    public JComponent asJComponent() {
126
        if (this.ph == null) {
127
            try {
128
                updateForm();
129
            } catch (Exception ex) {
130
                throw new RuntimeException(ex);
131
            }
132
        }
133
        return this.panel;
134
    }
135

    
136
    @Override
137
    public void bind(FeatureStore store) {
138
        if (store == null) {
139
            throw new IllegalArgumentException("bind need a store as parameter, not a null.");
140
        }
141
        try {
142
            DefaultDataSwingManager manager = (DefaultDataSwingManager) DALSwingLocator.getSwingManager();
143
            DynClass theDefinition = manager.featureType2DynClass(store, store.getDefaultFeatureType());
144
            this.bind(store, theDefinition);
145
        } catch (Exception ex) {
146
            throw new RuntimeException("Can't bind store '" + store.getName() + "' to form", ex);
147
        }
148
    }
149

    
150
    public void bind(FeatureStore store, DynClass definition) throws ServiceException, DataException {
151
        if (this.store == store) {
152
            return;
153
        }
154
        DynFormManager formManager = DynFormLocator.getDynFormManager();
155
        this.definition = formManager.getDefinition(definition);
156
        if (formset != null) {
157
            this.panel.remove(formset.asJComponent());
158
            this.formset = null;
159
        }
160
        this.store = store;
161
        this.ph = null;
162

    
163
    }
164

    
165
    @Override
166
    public JDynFormSet getFormset() {
167
        if (this.formset == null) {
168
            DynFormManager formManager = DynFormLocator.getDynFormManager();
169
            try {
170
                this.formset = formManager.createJDynFormSet(this.definition);
171
            } catch (ServiceException ex) {
172
                throw new RuntimeException("Can't create form set.", ex);
173
            }
174
            List<String> groups = this.definition.getGroups();
175
            if( groups.size()==1 && groups.get(0)==null ) {
176
                this.formset.setLayoutMode(JDynForm.USE_PLAIN);
177
            } else {
178
                this.formset.setLayoutMode(JDynForm.USE_TABS);
179
            }
180
            this.formset.setAllowNew(true);
181
            this.formset.setAllowDelete(true);
182
            this.formset.setAllowUpdate(true);
183
            this.formset.setAllowClose(true);
184
            this.formset.setAllowSearch(true);
185
            this.formset.setAutosave(true);
186

    
187
            this.formset.addAction(new StartEditingAction());
188
            this.formset.addAction(new FinishEditingAction());
189
            for( Action action : this.otherActions ) {
190
                this.formset.addAction(action);
191
            }
192

    
193
            this.formset.addListener(new FormSetListener());
194
        }
195
        if( this.store.isEditing() ) {
196
            this.formset.setReadOnly(false);
197
            formset.setActionVisible("startEditing", false);
198
            formset.setActionEnabled("startEditing", false);
199
            formset.setActionVisible("finishEditing", true);
200
            formset.setActionEnabled("finishEditing", true);
201
        } else {
202
            this.formset.setReadOnly(true);
203
            formset.setActionVisible("startEditing", true);
204
            formset.setActionEnabled("startEditing", true);
205
            formset.setActionVisible("finishEditing", false);
206
            formset.setActionEnabled("finishEditing", false);
207
        }
208
        return this.formset;
209
    }
210

    
211
    @Override
212
    public void addAction(Action action) {
213
        this.otherActions.add(action);
214
        if( this.formset!=null ) {
215
            this.formset.addAction(action);
216
        }
217
    }
218

    
219
    @Override
220
    public long getCurrentIndex() {
221
        if( this.formset==null ) {
222
            return -1;
223
        }
224
        return this.formset.getCurrentIndex();
225
    }
226

    
227
    @Override
228
    public Feature get(long index) {
229
        if( this.formset==null || this.ph==null ) {
230
            return null;
231
        }
232
        try {
233
            return this.ph.getFeatureAt(index);
234
        } catch (BaseException ex) {
235
            return null;
236
        }
237
    }
238

    
239
    private class FinishEditingAction extends AbstractAction implements Observer {
240

    
241
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
242
        public FinishEditingAction() {
243
            I18nManager i18nManager = ToolsLocator.getI18nManager();
244
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
245

    
246
            this.putValue(NAME,null);
247
            this.putValue(SHORT_DESCRIPTION,i18nManager.getTranslation("_Stop_editing"));
248
            this.putValue(SMALL_ICON, iconTheme.get("table-stop-editing"));
249
            this.putValue(ACTION_COMMAND_KEY, "finishEditing");
250

    
251
            this.setEnabled(store.isEditing());
252
            store.addObserver(this);
253
        }
254

    
255
        @Override
256
        public void actionPerformed(ActionEvent ae) {
257
            if( store.isEditing() ) {
258
                try {
259
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
260
                    ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
261
                    int x = dialogManager.confirmDialog(
262
                            "? Desea terminar edicion y guardar los cambios ?\n\nPulse cancelar para cancelar la edicion y los cambios.",
263
                            i18nManager.getTranslation("_Stop_editing"),
264
                            JOptionPane.YES_NO_CANCEL_OPTION,
265
                            JOptionPane.QUESTION_MESSAGE
266
                    );
267
                    switch(x) {
268
                        case JOptionPane.YES_OPTION:
269
                            store.finishEditing();
270
                            break;
271
                        case JOptionPane.NO_OPTION:
272
                            break;
273
                        case JOptionPane.CANCEL_OPTION:
274
                            store.cancelEditing();
275
                            break;
276
                    }
277
                } catch (DataException ex) {
278
                    LOGGER.warn("Can't finish editing in FeatureForm ("+store.getName()+").",ex);
279
                }
280
            }
281
        }
282

    
283
        @Override
284
        public void update(Observable observable, Object notification) {
285
            if( notification instanceof FeatureStoreNotification ) {
286
                FeatureStoreNotification n =  (FeatureStoreNotification) notification;
287
                switch( n.getType() )  {
288
                    case FeatureStoreNotification.AFTER_STARTEDITING:
289
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
290
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
291
                        if( store.isEditing() ) {
292
                            formset.setReadOnly(false);
293
                            formset.setActionVisible("finishEditing", true);
294
                            formset.setActionEnabled("finishEditing", true);
295
                        } else {
296
                            formset.setReadOnly(true);
297
                            formset.setActionVisible("finishEditing", false);
298
                            formset.setActionEnabled("finishEditing", false);
299
                        }
300
                        break;
301
                }
302
            }
303
        }
304

    
305
    }
306

    
307
    private class StartEditingAction extends AbstractAction implements Observer {
308

    
309
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
310
        public StartEditingAction() {
311
            I18nManager i18nManager = ToolsLocator.getI18nManager();
312
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
313

    
314
            this.putValue(NAME,null);
315
            this.putValue(SHORT_DESCRIPTION,i18nManager.getTranslation("_Start_editing"));
316
            this.putValue(SMALL_ICON, iconTheme.get("table-start-editing"));
317
            this.putValue(ACTION_COMMAND_KEY, "startEditing");
318

    
319
            this.setEnabled(!store.isEditing());
320
            store.addObserver(this);
321
        }
322

    
323
        @Override
324
        public void actionPerformed(ActionEvent ae) {
325
            if( !store.isEditing() ) {
326
                try {
327
                    store.edit();
328
                } catch (DataException ex) {
329
                    LOGGER.warn("Can't finish editing in FeatureForm ("+store.getName()+").",ex);
330
                }
331
            }
332
        }
333

    
334
        @Override
335
        public void update(Observable observable, Object notification) {
336
            if( notification instanceof FeatureStoreNotification ) {
337
                FeatureStoreNotification n =  (FeatureStoreNotification) notification;
338
                switch( n.getType() )  {
339
                    case FeatureStoreNotification.AFTER_STARTEDITING:
340
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
341
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
342
                        if( store.isEditing() ) {
343
                            formset.setReadOnly(false);
344
                            formset.setActionVisible("startEditing", false);
345
                            formset.setActionEnabled("startEditing", false);
346
                        } else {
347
                            formset.setReadOnly(true);
348
                            formset.setActionVisible("startEditing", true);
349
                            formset.setActionEnabled("startEditing", true);
350
                        }
351
                        break;
352
                }
353
            }
354
        }
355

    
356
    }
357

    
358
    @Override
359
    public void setQuery(FeatureQuery query) {
360
        if (this.ph != null) {
361
            if (this.formset != null && !formset.isReadOnly() && this.formset.isAutosave() && this.formset.countValues() > 0) {
362
                if (!store.isEditing()) {
363
                    try {
364
                        store.edit();
365
                    } catch (DataException e1) {
366
                        throw new RuntimeException("Can't set query", e1);
367
                    }
368
                }
369
                saveChanges(this.formset);
370
            }
371
        }
372
        this.currentQuery = query;
373
        updateForm();
374
    }
375

    
376
    private FeatureQuery getCurrentQuery() {
377
        return this.currentQuery;
378
    }
379
    
380
    @Override
381
    public void showForm(MODE mode) {
382
        this.panel.add(this.getFormset().asJComponent(), BorderLayout.CENTER);
383
        WindowManager winmgr = ToolsSwingLocator.getWindowManager();
384
        String title = this.definition.getLabel();
385
        winmgr.showWindow(this.asJComponent(), title, mode);
386
    }
387

    
388
    private void saveChanges(JDynFormSet dynformSet) {
389
        if( dynformSet.isInNewState() ) {
390
            Feature feat = null;
391
            try {
392
                feat = store.createNewFeature(false);
393
            } catch (DataException ex) {
394
                LOGGER.warn("Can't create new feature.",ex);
395
                I18nManager i18nManager = ToolsLocator.getI18nManager();
396
                dynformSet.message(i18nManager.getTranslation("error_saving_data_will_not_save"));
397
                throw new RuntimeException("Can't new save values");
398
            }
399
            DynObject dynObject = feat.getAsDynObject();
400
            dynformSet.getFormValues(dynObject);
401
            try {
402
                ph.insert(((FacadeOfAFeature)dynObject).getEditableFeature());
403
            } catch (BaseException e) {
404
                throw new RuntimeException("Can't save values", e);
405
            }
406
            try {
407
                this.formset.setValues(ph.asListOfDynObjects());
408
                this.formset.setCurrentIndex((int)(ph.getTotalSize())-1);
409
            } catch(Exception ex) {
410
                LOGGER.warn("Can't reload form data after insert.",ex);
411
            }
412
        } else {
413
            int index = dynformSet.getCurrentIndex();
414
            DynObject dynObject = dynformSet.get(index);
415

    
416
            if ( !(dynObject instanceof FacadeOfAFeature) ) {
417
                LOGGER.warn("Can't get the associated feature index " + index);
418
                I18nManager i18nManager = ToolsLocator.getI18nManager();
419
                dynformSet.message(i18nManager.getTranslation("error_saving_data_will_not_save"));
420
                throw new RuntimeException("Can't save values");
421
            }
422
            dynformSet.getFormValues(dynObject);
423
            try {
424
                ph.update(((FacadeOfAFeature)dynObject).getEditableFeature());
425
            } catch (BaseException e) {
426
                throw new RuntimeException("Can't save values", e);
427
            }
428
        }
429

    
430
    }
431

    
432
    @Override
433
    public void saveChanges() {
434
        if (this.formset != null && this.formset.countValues() > 0) {
435
            if (store != null && !store.isEditing()) {
436
                try {
437
                    store.edit();
438
                } catch (DataException e1) {
439
                    LOGGER.warn("Can't edit the store " + store.getName());
440
                    throw new RuntimeException("Can't save changes.", e1);
441
                }
442
            }
443
            this.saveChanges(this.formset);
444
        }
445
    }
446

    
447
    @Override
448
    public long getDataSetSize() {
449
        if (this.ph != null) {
450
            return ph.getTotalSize();
451
        }
452
        return 0;
453
    }
454

    
455
    @Override
456
    public FeatureStore getFeatureStore() {
457
        return this.store;
458
    }
459

    
460
    private class FormSetListener implements JDynFormSetListener {
461

    
462
        @Override
463
        public void formMessage(String message) {
464
        }
465

    
466
        @Override
467
        public void formClose() {
468
            panel.setVisible(false);
469
        }
470

    
471
        @Override
472
        public void formMovedTo(int currentPosition) throws AbortActionException {
473
            LOGGER.trace("formMovedTo " + currentPosition);
474
        }
475

    
476
        @Override
477
        public void formBeforeSave(JDynFormSet dynformSet) throws AbortActionException {
478
            LOGGER.trace("formBeforeSave");
479
            if (!store.isEditing()) {
480
                try {
481
                    store.edit();
482
                } catch (DataException e1) {
483
                    throw new StoreEditException(e1, store.getName());
484
                }
485
            }
486
        }
487

    
488
        public void formBeforeNew(JDynFormSet dynformSet) throws AbortActionException {
489
            LOGGER.trace("formBeforeNew");
490
        }
491

    
492
        public void formBeforeDelete(JDynFormSet dynformSet) throws AbortActionException {
493
            LOGGER.trace("formBeforeDelete");
494
        }
495

    
496
        @Override
497
        public void formAfterSave(JDynFormSet dynformSet) throws AbortActionException {
498
            LOGGER.trace("formAfterSave");
499
            saveChanges(dynformSet);
500
        }
501

    
502
        @Override
503
        public void formAfterNew(JDynFormSet dynformSet) throws AbortActionException {
504
            LOGGER.trace("formAfterNew");
505
        }
506

    
507
        @Override
508
        public void formAfterDelete(JDynFormSet dynformSet) throws AbortActionException {
509
            LOGGER.trace("formAfterDelete");
510
        }
511

    
512
        @Override
513
        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
514
            LOGGER.trace("formBeforeSearch");
515
            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
516
            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
517

    
518
            JExpressionBuilder builder = dataSwingmanager.createQueryFilterExpresion(store);
519
            FeatureQuery currentQuery = getCurrentQuery();
520
            if( currentQuery!=null ) {
521
                Evaluator filter = currentQuery.getFilter();
522
                if( filter instanceof ExpressionEvaluator ) {
523
                    Expression expression = ((ExpressionEvaluator)filter).getExpression();
524
                    builder.setExpression(expression);
525
                }
526
            }
527
            Dialog dialog = winmgr.createDialog(
528
                    builder.asJComponent(),
529
                    "Filtro",
530
                    "Creacion de filtro sobre '"+store.getName()+"'",
531
                    WindowManager_v2.BUTTONS_OK_CANCEL
532
            );
533
            dialog.show(WindowManager.MODE.DIALOG);
534
            if( dialog.getAction() == WindowManager_v2.BUTTON_OK ) {
535
                Expression expresion = builder.getExpression();
536
                try {
537
                    FeatureQuery query = store.createFeatureQuery();
538
                    if( ExpressionUtils.isPhraseEmpty(expresion) ) {
539
                        query.clearFilter();
540
                    } else {
541
                        query.setFilter(expresion);
542
                    }
543
                    setQuery(query);
544
                } catch (Exception ex) {
545
                    LOGGER.warn("Can't apply filter '" + expresion + "'.", ex);
546
                }
547
            }
548
        }
549

    
550
        @Override
551
        public void formAfterSearch(JDynFormSet dynformSet) throws AbortActionException {
552
            LOGGER.trace("formAfterSearch");
553
        }
554

    
555
        @Override
556
        public void formBeforeCancelNew(JDynFormSet dynformSet) throws AbortActionException {
557
            LOGGER.trace("formBeforeCancelNew");
558
        }
559

    
560
        @Override
561
        public void formAfterCancelNew(JDynFormSet dynformSet) throws AbortActionException {
562
            LOGGER.trace("formAfterCancelNew");
563
        }
564
    }
565

    
566
    private static class StoreEditException extends AbortActionException {
567

    
568
        /**
569
         *
570
         */
571
        private static final long serialVersionUID = -7682017811778577130L;
572

    
573
        public StoreEditException(Throwable cause, String storename) {
574
            super("Can't edit the store '%(storename)'", cause, "cant_edit_the store_XstorenameX", serialVersionUID);
575
            setValue("storename", storename);
576
        }
577
    }
578
}