Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / EditionManager.java @ 38560

History | View | Annotate | Download (15.8 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.editing;
23

    
24
import java.awt.BorderLayout;
25
import java.awt.Dimension;
26
import java.awt.ScrollPane;
27
import java.util.ArrayList;
28
import java.util.Iterator;
29
import java.util.List;
30

    
31
import javax.swing.JOptionPane;
32
import javax.swing.JPanel;
33
import javax.swing.SwingUtilities;
34

    
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37

    
38
import org.gvsig.andami.PluginServices;
39
import org.gvsig.andami.messages.NotificationManager;
40
import org.gvsig.andami.ui.mdiManager.IWindow;
41
import org.gvsig.app.ApplicationLocator;
42
import org.gvsig.app.project.documents.view.gui.DefaultViewPanel;
43
import org.gvsig.editing.layers.FactoryLayerEdited;
44
import org.gvsig.editing.layers.ILayerEdited;
45
import org.gvsig.editing.layers.VectorialLayerEdited;
46
import org.gvsig.fmap.dal.exception.DataException;
47
import org.gvsig.fmap.dal.exception.DataRuntimeException;
48
import org.gvsig.fmap.dal.feature.AbstractFeatureRule;
49
import org.gvsig.fmap.dal.feature.EditableFeature;
50
import org.gvsig.fmap.dal.feature.Feature;
51
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.FeatureRule;
53
import org.gvsig.fmap.dal.feature.FeatureRules;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.dal.feature.FeatureType;
56
import org.gvsig.fmap.mapcontext.layers.CancelationException;
57
import org.gvsig.fmap.mapcontext.layers.FLayer;
58
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
59
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
60
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
61
import org.gvsig.fmap.mapcontext.layers.LayerListener;
62
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
63
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
64
import org.gvsig.fmap.mapcontrol.MapControl;
65
import org.gvsig.gui.beans.buttonspanel.ButtonsPanel;
66
import org.gvsig.gui.beans.buttonspanel.ButtonsPanelEvent;
67
import org.gvsig.gui.beans.buttonspanel.ButtonsPanelListener;
68
import org.gvsig.tools.swing.api.ToolsSwingLocator;
69
import org.gvsig.tools.swing.api.dynobject.DynObjectSwingManager;
70
import org.gvsig.tools.swing.api.dynobject.JDynObjectComponent;
71
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
72

    
73
/**
74
 * 
75
 * El prop?sito de esta clase es centralizar el manejo de la
76
 * edici?n. Aqu? podemos encontrar una lista con todas
77
 * los temas en edici?n, y las propiedades que sean globales
78
 * e interesantes a la hora de ponerse a editar.
79
 * Por ejemplo, podemos poner aqu? el Grid que vamos a usar,
80
 * el MapControl que tenemos asociado, etc, etc.
81
 * Tambi?n ser? el responsable de mantener una lista de
82
 * listeners interesados en los eventos de edici?n, y
83
 * de lanzar los eventos que necesitemos.
84
 * Lo principal es una colecci?n de LayerEdited, y cada
85
 * LayerEdited es un wrapper alrededor de un tema que guarda
86
 * las propiedades de la edici?n.
87
 * 
88
 * Nuevo: Llevar aqu? el control de las tablas en edici?n tambi?n
89
 * y centralizar los listeners interesados en los eventos de edici?n.
90
 * 
91
 * TODO: Poner todo lo referente al EditionManager dentro de una vista.
92
 * para permitir tener varias vistas con temas en edici?n
93
 * 
94
 * @author fjp
95
 */
96
public class EditionManager implements LayerListener, LayerCollectionListener {
97

    
98
    private static final Logger LOG = LoggerFactory
99
        .getLogger(EditionManager.class);
100

    
101
    private List<ILayerEdited> editedLayers = new ArrayList<ILayerEdited>();
102
    private MapControl mapCtrl = null;
103
    private ILayerEdited ile = null;
104

    
105
    /**
106
     * @param lyr
107
     * @return
108
     */
109
    public ILayerEdited getLayerEdited(FLayer lyr) {
110
        ILayerEdited aux = null;
111
        for (int i = 0; i < editedLayers.size(); i++) {
112
            aux = editedLayers.get(i);
113
            if (aux.getLayer() == lyr)
114
                return aux;
115
        }
116
        return null;
117
    }
118

    
119
    public void visibilityChanged(LayerEvent e) {
120
    }
121

    
122
    public void activationChanged(LayerEvent e) {
123
        if (e.getSource().isActive()) {
124
            ile = getLayerEdited(e.getSource());
125
        }
126
        if (ile == null || ile.getLayer().equals(e.getSource())) {
127

    
128
            if (ile != null && !ile.getLayer().isActive()) {
129
                VectorialLayerEdited lastVLE = (VectorialLayerEdited) ile;
130
                lastVLE.activationLost(e);
131
            }
132
            if (e.getSource() instanceof FLyrVect) {
133
                VectorialLayerEdited vle = null;
134
                vle = (VectorialLayerEdited) getLayerEdited(e.getSource());
135
                ile = vle;
136
                if (getMapControl() != null && vle != null
137
                    && vle.getLayer().isActive()) {
138
                    getMapControl().setTool("cadtooladapter");
139
                    vle.activationGained(e);
140
                    return;
141
                }
142
            }
143
            if (getMapControl() != null) {
144
                getMapControl().setTool("zoomIn");
145
                PluginServices.getMainFrame().setSelectedTool("ZOOM_IN");
146
            }
147
        }
148
    }
149

    
150
    public void nameChanged(LayerEvent e) {
151
    }
152

    
153
    public void editionChanged(LayerEvent e) {
154
        ILayerEdited lyrEdit = getLayerEdited(e.getSource());
155

    
156
        // Si no est? en la lista, comprobamos que est? en edici?n
157
        // y lo a?adimos
158
        if ((lyrEdit == null) && e.getSource().isEditing()) {
159
            lyrEdit =
160
                FactoryLayerEdited.createLayerEdited(e.getSource(), mapCtrl);
161
            editedLayers.add(lyrEdit);
162
            if (getMapControl() != null) {
163
                getMapControl().setTool("cadtooladapter");
164
                CADExtension.setCADTool("_selection", true);
165
            }
166
            PluginServices.getMainFrame().setSelectedTool("_selection");
167
            // idActiveLayer = editedLayers.size() - 1;
168
            ile = getLayerEdited(e.getSource());
169
            LOG.debug("NUEVA CAPA EN EDICION: {}", lyrEdit.getLayer().getName());
170

    
171
            // Ponemos el resto de temas desactivados
172
            if (mapCtrl != null)
173
                mapCtrl.getMapContext().getLayers().setActive(false);
174
            // y activamos el nuevo.
175
            e.getSource().setActive(true);
176

    
177
            if (e.getSource() instanceof FLyrVect) {
178
                FLyrVect fLyrVect = (FLyrVect) e.getSource();
179
                ((VectorialLayerEdited) lyrEdit)
180
                    .setEditionChangeManager(new EditionChangeManager(fLyrVect));
181

    
182
                addCheckRules(fLyrVect);
183
            }
184
        } else {
185
            for (int i = 0; i < editedLayers.size(); i++) {
186
                VectorialLayerEdited vle =
187
                    (VectorialLayerEdited) editedLayers.get(i);
188
                if (vle.equals(lyrEdit)) {
189
                    editedLayers.remove(i);
190
                    ile = null;
191
                    return;
192
                }
193
            }
194
        }
195

    
196
    }
197

    
198
    /**
199
     * @return Returns the activeLayerEdited. Null if there isn't any active AND
200
     *         edited
201
     */
202
    public ILayerEdited getActiveLayerEdited() {
203
        return ile;
204
    }
205

    
206
    /**
207
     * @return Returns the mapCtrl.
208
     */
209
    public MapControl getMapControl() {
210
        return mapCtrl;
211
    }
212

    
213
    /**
214
     * @param mapCtrl
215
     *            The mapCtrl to set.
216
     */
217
    public void setMapControl(MapControl mapCtrl) {
218
        if (mapCtrl != null) {
219
            this.mapCtrl = mapCtrl;
220
            mapCtrl.getMapContext().getLayers().addLayerListener(this);
221
            mapCtrl.getMapContext().getLayers()
222
                .addLayerCollectionListener(this);
223
        }
224
    }
225

    
226
    public void layerAdded(LayerCollectionEvent e) {
227
        // Nothing to do
228

    
229
    }
230

    
231
    public void layerMoved(LayerPositionEvent e) {
232
        // Nothing to do
233
    }
234

    
235
    public void layerRemoved(LayerCollectionEvent e) {
236
        VectorialLayerEdited vle =
237
            (VectorialLayerEdited) getActiveLayerEdited();
238
        if (vle != null && vle.getLayer().isActive()) {
239
            try {
240
                vle.clearSelection();
241
            } catch (DataException e1) {
242
                NotificationManager.addError(e1);
243
            }
244
            editedLayers.remove(vle);
245
            getMapControl().setTool("zoomIn");
246
            FLyrVect lv = (FLyrVect) vle.getLayer();
247
            if (e.getAffectedLayer().equals(lv)) {
248
                IWindow window =
249
                    PluginServices.getMDIManager().getActiveWindow();
250
                if (window instanceof DefaultViewPanel) {
251
                    DefaultViewPanel view = (DefaultViewPanel) window;
252
                    view.hideConsole();
253
                    view.validate();
254
                    view.repaint();
255
                }
256
            }
257
        }
258
        PluginServices.getMainFrame().enableControls();
259
    }
260

    
261
    public void layerAdding(LayerCollectionEvent e) throws CancelationException {
262
        // Nothing to do
263
    }
264

    
265
    public void layerMoving(LayerPositionEvent e) throws CancelationException {
266
        // Nothing to do
267
    }
268

    
269
    public void layerRemoving(LayerCollectionEvent e)
270
        throws CancelationException {
271
        // Nothing to do
272
    }
273

    
274
    public void activationChanged(LayerCollectionEvent e)
275
        throws CancelationException {
276
        // Nothing to do
277
    }
278

    
279
    public void visibilityChanged(LayerCollectionEvent e)
280
        throws CancelationException {
281
        // Nothing to do
282
    }
283

    
284
    public void drawValueChanged(LayerEvent e) {
285
        // Nothing to do
286
    }
287

    
288
    class CheckMandatoryAttributtes extends AbstractFeatureRule {
289

    
290
        protected CheckMandatoryAttributtes() {
291
            super("CheckMandatoryAttributtes", "CheckMandatoryAttributtes");
292
        }
293

    
294
        public void validate(Feature feature, FeatureStore featureStore)
295
            throws DataException {
296
            // Comprobar si hay campos obligatorios y presentar formulario
297
            FeatureType featureType = feature.getType();
298
            FeatureAttributeDescriptor[] attributeDescriptors =
299
                featureType.getAttributeDescriptors();
300
            boolean showForm = false;
301
            for (int i = 0; i < attributeDescriptors.length; i++) {
302
                FeatureAttributeDescriptor attrDesc = attributeDescriptors[i];
303
                if ((attrDesc.isPrimaryKey() || !attrDesc.allowNull())
304
                    && feature.get(attrDesc.getName()) == null) {
305
                    showForm = true;
306
                    break;
307
                }
308
            }
309
            if (showForm) {
310
                askRequiredAttributtes((EditableFeature) feature, featureStore);
311
            }
312
        }
313

    
314
    }
315

    
316
    private void askRequiredAttributtes(final EditableFeature feature,
317
        final FeatureStore store)
318
        throws FeatureRuleMandatoryAttributesException {
319

    
320
        // Comprobar que estamos en el thread de swing y si no excepcion
321
        if (!SwingUtilities.isEventDispatchThread()) {
322
            try {
323
                SwingUtilities.invokeAndWait(new Runnable() {
324

    
325
                    public void run() {
326
                        askRequiredAttributtes(feature, store);
327
                    }
328
                });
329
            } catch (Exception e1) {
330
                throw new FeatureRuleMandatoryAttributesException(e1,
331
                    store.getFullName());
332
            }
333
            return;
334
        }
335
        DynObjectSwingManager dynObjectSwinManager =
336
            ToolsSwingLocator.getDynObjectSwingManager();
337
        final JDynObjectComponent dynObjectComponent;
338
        try {
339
            dynObjectComponent =
340
                dynObjectSwinManager.createJDynObjectComponent(
341
                    feature.getAsDynObject(), true);
342
        } catch (Exception e) {
343
            
344
            // TODO This has to be improved
345
            // Instead of this warning, show dialog to
346
            // fill feature type 
347
            showBadValuesMessage(e.getMessage());
348
            return;
349
            
350
        }
351
        final JPanel panel = new JPanel();
352

    
353
        ButtonsPanel buttonsPanel =
354
            new ButtonsPanel(ButtonsPanel.BUTTONS_ACCEPTCANCEL);
355
        buttonsPanel.addButtonPressedListener(new ButtonsPanelListener() {
356

    
357
            public void actionButtonPressed(ButtonsPanelEvent e) {
358
                if (e.getButton() == ButtonsPanel.BUTTON_ACCEPT) {
359
                    dynObjectComponent.saveStatus();
360
                    panel.setVisible(false);
361
                }
362
                if (e.getButton() == ButtonsPanel.BUTTON_CANCEL) {
363
                    panel.setVisible(false);
364
                    throw new FeatureRuleMandatoryAttributesException(store
365
                        .getFullName());
366
                }
367
            }
368

    
369
        });
370
        panel.setLayout(new BorderLayout());
371
        ScrollPane scrollPanel = new ScrollPane();
372
        scrollPanel.add(dynObjectComponent.asJComponent(), BorderLayout.CENTER);
373
        panel.add(scrollPanel);
374
        panel.add(buttonsPanel, BorderLayout.SOUTH);
375
        panel.setPreferredSize(new Dimension(800, 600));
376
        WindowManager wm = ToolsSwingLocator.getWindowManager();
377
        wm.showWindow(panel, "Fill mandatory fields", WindowManager.MODE.DIALOG);
378

    
379
    }
380

    
381
    /**
382
     * @param message
383
     */
384
    private void showBadValuesMessage(String message) {
385
        
386
        ApplicationLocator.getManager().message(
387
            message,
388
            JOptionPane.WARNING_MESSAGE);
389
        
390
        /*
391
         * We cannot do this because window focus
392
         * causes exception in drawing
393
         * 
394
        IWindow iw = PluginServices.getMDIManager().getActiveWindow();
395
        Component pare = null;
396
        if (iw instanceof Component) {
397
            pare = (Component) iw;
398
        }
399
        
400
        String _tit = Messages.getText("editing");
401
        String _msg = Messages.getText("_Invalid_values_in_some_fields_must_be_edited_before_end_editing");
402
        _msg = _msg + "\n\n[" + message + "]";
403
        
404
        JOptionPane.showMessageDialog(
405
            pare,
406
            _msg, _tit,
407
            JOptionPane.WARNING_MESSAGE);
408
            */
409
    }
410

    
411
    private void addCheckRules(FLyrVect layer) {
412
        try {
413
            FeatureType featureType =
414
                layer.getFeatureStore().getDefaultFeatureType();
415
            FeatureRules featureRules = featureType.getRules();
416
            for (Iterator it = featureRules.iterator(); it.hasNext();) {
417
                FeatureRule rule = (FeatureRule) it.next();
418
                if (rule instanceof CheckMandatoryAttributtes) {
419
                    return;
420
                }
421
            }
422
            featureRules.add(new CheckMandatoryAttributtes());
423
        } catch (DataException e) {
424
            throw new RuntimeException(e);
425
        }
426
    }
427

    
428
    public class FeatureRuleMandatoryAttributesException extends
429
        DataRuntimeException {
430

    
431
        private static final long serialVersionUID = -7965533441336164612L;
432
        private final static String MESSAGE_FORMAT =
433
            "Can't apply rule in store %(store)s.";
434
        private final static String MESSAGE_KEY =
435
            "_FeatureRuleMandatoryAttributesException";
436

    
437
        public FeatureRuleMandatoryAttributesException(Throwable cause,
438
            String store) {
439
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
440
            this.setValue("store", store);
441
        }
442

    
443
        public FeatureRuleMandatoryAttributesException(String store) {
444
            super(MESSAGE_FORMAT, MESSAGE_KEY, serialVersionUID);
445
            this.setValue("store", store);
446
        }
447
    }
448

    
449
}