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

History | View | Annotate | Download (21 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.swing.JExpressionBuilder;
42

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

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

    
81
/**
82
 * @author fdiaz
83
 *
84
 */
85
@SuppressWarnings("UseSpecificCatch")
86
public class DefaultJFeaturesForm implements JFeaturesForm {
87

    
88
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJFeaturesForm.class);
89

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

    
99
    public DefaultJFeaturesForm() {
100
        this.panel = new JPanel(new BorderLayout());
101
        this.otherActions = new ArrayList<>();
102
    }
103

    
104
    @Override
105
    public void setPreferredSize(Dimension dimension) {
106
        panel.setPreferredSize(dimension);
107
    }
108

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

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

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

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

    
160
    }
161

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

    
184
            this.formset.addAction(new StartEditingAction());
185
            this.formset.addAction(new FinishEditingAction());
186
            for( Action action : this.otherActions ) {
187
                this.formset.addAction(action);
188
            }
189

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

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

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

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

    
236
    private class FinishEditingAction extends AbstractAction implements Observer {
237

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

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

    
248
            this.setEnabled(store.isEditing());
249
            store.addObserver(this);
250
        }
251

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

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

    
302
    }
303

    
304
    private class StartEditingAction extends AbstractAction implements Observer {
305

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

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

    
316
            this.setEnabled(!store.isEditing());
317
            store.addObserver(this);
318
        }
319

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

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

    
353
    }
354

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

    
373
    @Override
374
    public void showForm(MODE mode) {
375
        this.panel.add(this.getFormset().asJComponent(), BorderLayout.CENTER);
376
        WindowManager winmgr = ToolsSwingLocator.getWindowManager();
377
        String title = this.definition.getLabel();
378
        winmgr.showWindow(this.asJComponent(), title, mode);
379
    }
380

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

    
409
            if ( !(dynObject instanceof FacadeOfAFeature) ) {
410
                LOGGER.warn("Can't get the associated feature index " + index);
411
                I18nManager i18nManager = ToolsLocator.getI18nManager();
412
                dynformSet.message(i18nManager.getTranslation("error_saving_data_will_not_save"));
413
                throw new RuntimeException("Can't save values");
414
            }
415
            dynformSet.getFormValues(dynObject);
416
            try {
417
                ph.update(((FacadeOfAFeature)dynObject).getEditableFeature());
418
            } catch (BaseException e) {
419
                throw new RuntimeException("Can't save values", e);
420
            }
421
        }
422

    
423
    }
424

    
425
    @Override
426
    public void saveChanges() {
427
        if (this.formset != null && this.formset.countValues() > 0) {
428
            if (store != null && !store.isEditing()) {
429
                try {
430
                    store.edit();
431
                } catch (DataException e1) {
432
                    LOGGER.warn("Can't edit the store " + store.getName());
433
                    throw new RuntimeException("Can't save changes.", e1);
434
                }
435
            }
436
            this.saveChanges(this.formset);
437
        }
438
    }
439

    
440
    @Override
441
    public long getDataSetSize() {
442
        if (this.ph != null) {
443
            return ph.getTotalSize();
444
        }
445
        return 0;
446
    }
447

    
448
    @Override
449
    public FeatureStore getFeatureStore() {
450
        return this.store;
451
    }
452

    
453
    private class FormSetListener implements JDynFormSetListener {
454

    
455
        @Override
456
        public void formMessage(String message) {
457
        }
458

    
459
        @Override
460
        public void formClose() {
461
            panel.setVisible(false);
462
        }
463

    
464
        @Override
465
        public void formMovedTo(int currentPosition) throws AbortActionException {
466
            LOGGER.trace("formMovedTo " + currentPosition);
467
        }
468

    
469
        @Override
470
        public void formBeforeSave(JDynFormSet dynformSet) throws AbortActionException {
471
            LOGGER.trace("formBeforeSave");
472
            if (!store.isEditing()) {
473
                try {
474
                    store.edit();
475
                } catch (DataException e1) {
476
                    throw new StoreEditException(e1, store.getName());
477
                }
478
            }
479
        }
480

    
481
        public void formBeforeNew(JDynFormSet dynformSet) throws AbortActionException {
482
            LOGGER.trace("formBeforeNew");
483
        }
484

    
485
        public void formBeforeDelete(JDynFormSet dynformSet) throws AbortActionException {
486
            LOGGER.trace("formBeforeDelete");
487
        }
488

    
489
        @Override
490
        public void formAfterSave(JDynFormSet dynformSet) throws AbortActionException {
491
            LOGGER.trace("formAfterSave");
492
            saveChanges(dynformSet);
493
        }
494

    
495
        @Override
496
        public void formAfterNew(JDynFormSet dynformSet) throws AbortActionException {
497
            LOGGER.trace("formAfterNew");
498
        }
499

    
500
        @Override
501
        public void formAfterDelete(JDynFormSet dynformSet) throws AbortActionException {
502
            LOGGER.trace("formAfterDelete");
503
        }
504

    
505
        @Override
506
        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
507
            LOGGER.trace("formBeforeSearch");
508
            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
509
            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
510

    
511
            JExpressionBuilder builder = dataSwingmanager.createQueryFilterExpresion(store);
512
            Dialog dialog = winmgr.createDialog(
513
                    builder.asJComponent(),
514
                    "Filtro",
515
                    "Creacion de filtro sobre '"+store.getName()+"'",
516
                    WindowManager_v2.BUTTONS_OK_CANCEL
517
            );
518
            dialog.show(WindowManager.MODE.DIALOG);
519
            if( dialog.getAction() == WindowManager_v2.BUTTON_OK ) {
520
                Expression expresion = builder.getExpression();
521
                try {
522
                    FeatureQuery query = store.createFeatureQuery();
523
                    if( !expresion.isPhraseEmpty() ) {
524
                        query.setFilter(expresion);
525
                    }
526
                    setQuery(query);
527
                } catch (Exception ex) {
528
                    LOGGER.warn("Can't apply filter '" + expresion + "'.", ex);
529
                }
530
            }
531
        }
532

    
533
        @Override
534
        public void formAfterSearch(JDynFormSet dynformSet) throws AbortActionException {
535
            LOGGER.trace("formAfterSearch");
536
        }
537

    
538
        @Override
539
        public void formBeforeCancelNew(JDynFormSet dynformSet) throws AbortActionException {
540
            LOGGER.trace("formBeforeCancelNew");
541
        }
542

    
543
        @Override
544
        public void formAfterCancelNew(JDynFormSet dynformSet) throws AbortActionException {
545
            LOGGER.trace("formAfterCancelNew");
546
        }
547
    }
548

    
549
    private static class StoreEditException extends AbortActionException {
550

    
551
        /**
552
         *
553
         */
554
        private static final long serialVersionUID = -7682017811778577130L;
555

    
556
        public StoreEditException(Throwable cause, String storename) {
557
            super("Can't edit the store '%(storename)'", cause, "cant_edit_the store_XstorenameX", serialVersionUID);
558
            setValue("storename", storename);
559
        }
560
    }
561
}