Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.app / org.gvsig.vectorediting.app.mainplugin / src / main / java / org / gvsig / vectorediting / app / mainplugin / EditingExtension.java @ 672

History | View | Annotate | Download (14 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 gvSIG Association
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.vectorediting.app.mainplugin;
25

    
26
import java.io.File;
27
import java.util.ArrayList;
28
import java.util.List;
29
import javax.swing.JOptionPane;
30
import org.apache.commons.io.FileUtils;
31

    
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35
import org.gvsig.andami.IconThemeHelper;
36
import org.gvsig.andami.PluginServices;
37
import org.gvsig.andami.plugins.Extension;
38
import org.gvsig.andami.plugins.IExtension;
39
import org.gvsig.andami.plugins.status.IExtensionStatus;
40
import org.gvsig.andami.plugins.status.IUnsavedData;
41
import org.gvsig.andami.plugins.status.UnsavedData;
42
import org.gvsig.andami.ui.mdiManager.IWindow;
43
import org.gvsig.andami.ui.mdiManager.SingletonWindow;
44
import org.gvsig.app.ApplicationLocator;
45
import org.gvsig.app.ApplicationManager;
46
import org.gvsig.app.project.Project;
47
import org.gvsig.app.project.documents.Document;
48
import org.gvsig.app.project.documents.gui.IDocumentWindow;
49
import org.gvsig.app.project.documents.view.ViewDocument;
50
import org.gvsig.app.project.documents.view.ViewManager;
51
import org.gvsig.app.project.documents.view.gui.DefaultViewPanel;
52
import org.gvsig.app.project.documents.view.gui.IView;
53
import org.gvsig.app.project.documents.view.toc.actions.EndEditingTocMenuEntry;
54
import org.gvsig.app.project.documents.view.toc.actions.StartEditingTocMenuEntry;
55
import org.gvsig.app.project.documents.view.toolListeners.StatusBarListener;
56
import org.gvsig.fmap.dal.exception.DataException;
57
import org.gvsig.fmap.dal.feature.FeatureStore;
58
import org.gvsig.fmap.mapcontext.MapContext;
59
import org.gvsig.fmap.mapcontext.MapContextLocator;
60
import org.gvsig.fmap.mapcontext.layers.FLayer;
61
import org.gvsig.fmap.mapcontext.layers.FLayers;
62
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
63
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
64
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
65
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
66
import org.gvsig.fmap.mapcontrol.MapControl;
67
import org.gvsig.fmap.mapcontrol.MapControlCreationListener;
68
import org.gvsig.fmap.mapcontrol.MapControlLocator;
69
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
70
import org.gvsig.fmap.mapcontrol.tools.Behavior.MouseMovementBehavior;
71
import org.gvsig.tools.ToolsLocator;
72
import org.gvsig.tools.extensionpoint.ExtensionPoint;
73
import org.gvsig.tools.observer.Notification;
74
import org.gvsig.tools.observer.Observable;
75
import org.gvsig.tools.observer.Observer;
76
import org.gvsig.utils.swing.threads.IMonitorableTask;
77
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
78
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
79
import org.gvsig.vectorediting.swing.api.EditingContext;
80
import org.gvsig.vectorediting.swing.api.EditingSwingLocator;
81
import org.gvsig.vectorediting.swing.api.EditingSwingManager;
82

    
83
public class EditingExtension extends Extension implements Observer {
84

    
85
    private static final Logger logger = LoggerFactory.getLogger(EditingExtension.class);
86

    
87
    @Override
88
    public void execute(String actionCommand) {
89

    
90
        ApplicationManager application = ApplicationLocator.getManager();
91
        IView view = getActiveView();
92
        EditingSwingManager swingManager = EditingSwingLocator.getSwingManager();
93

    
94
        if (view != null) {
95

    
96
            FLyrVect layer = getActiveLayer(view);
97
            MapControl mapControl = view.getMapControl();
98
            EditingContext editingContext = swingManager.getEditingContext(mapControl);
99

    
100
            if ("start-editing".equals(actionCommand)) {
101

    
102
                if (canBeEdited(layer)) {
103
                    if( !mapControl.getProjection().equals(layer.getProjection()) ) {
104
                        String msg = "_The_layer_is_reproyected_on_the_fly" 
105
                                + "_Not_all_editing_tools_work_properly"
106
                                + "_When_you_finish_editing"
107
                                + "_will_only_export_the_changes_to_another_layer";
108
                        application.messageDialog(msg, "_Warning", JOptionPane.WARNING_MESSAGE);
109
                    }
110
                    editingContext.beginEdition(layer);
111
                    editingContext.addObserver(this);
112
                    ApplicationLocator.getManager().refreshMenusAndToolBars();
113
                }
114

    
115
            } else if ("end-editing".equals(actionCommand)) {
116

    
117
                if ((layer != null) && layer.isEditing()) {
118
                    editingContext.endEdition(layer);
119
                    ApplicationLocator.getManager().refreshMenusAndToolBars();
120
                }
121

    
122
            }
123
        }
124
    }
125

    
126
    @Override
127
    public void initialize() {
128
        registerIcons();
129

    
130
        // Disable default view panel console. Uses editing context console.
131
        DefaultViewPanel.setDisableConsole(true);
132

    
133
        // Adding TOC menu entry
134
        ExtensionPoint exPoint = ToolsLocator.getExtensionPointManager().add(
135
                "View_TocActions", "");
136
        exPoint.append(
137
            StartEditingTocMenuEntry.EXTENSION_POINT_NAME,
138
                "TOC popup menu to start vector layer's editing",
139
                new StartEditingTocMenuEntry());
140
        exPoint.append(
141
            EndEditingTocMenuEntry.EXTENSION_POINT_NAME,
142
                "TOC popup menu to end vector layer's editing",
143
                new EndEditingTocMenuEntry());
144
    }
145

    
146

    
147
    private void registerIcons() {
148
        IconThemeHelper.registerIcon("vectorediting", "vector-editing", this);
149
    }
150

    
151
    @Override
152
    public void postInitialize() {
153
        super.postInitialize();
154
        registerSymbols();
155

    
156
        MapControlLocator.getMapControlManager().addMapControlCreationListener(new MapControlCreationListener() {
157

    
158
            @Override
159
            public MapControl mapControlCreated(MapControl mapControl) {
160
                EditingContext editingContext = EditingSwingLocator.getSwingManager().getEditingContext(mapControl);
161
                StatusBarListener sbl = new StatusBarListener(mapControl);
162
                editingContext.setDefaultBehaviors(new Behavior[] { new MouseMovementBehavior(sbl) });
163
                editingContext.addObserver(EditingExtension.this);
164
                ApplicationLocator.getManager().refreshMenusAndToolBars();
165
                return mapControl;
166
            }
167
        });
168
    }
169

    
170
    /**
171
     * Register all symbols in the plugin symbols folder in the providerManager.
172
     * The description of the symbols must be unique because the key used for registration is the proper description of the symbol.
173
     *
174
     */
175
    private void registerSymbols() {
176

    
177
        EditingProviderManager providerManager = EditingProviderLocator.getProviderManager();
178

    
179
        SymbolManager symbolManager = MapContextLocator.getSymbolManager();
180
        File symbolsFolder = FileUtils.getFile(getPlugin().getPluginDirectory(), "symbols","editing");
181
        ISymbol[] symbols = null;
182
        try {
183
            symbols = symbolManager.loadSymbols(symbolsFolder);
184
        } catch (SymbolException e) {
185
            logger.warn("No symbols loaded from "+symbolsFolder.getAbsolutePath(), e);
186
        }
187

    
188
        if (symbols != null) {
189
            for (ISymbol symbol : symbols) {
190
                String description = symbol.getDescription();
191
                providerManager.registerSymbol(description, symbol);
192
            }
193
        }
194
    }
195

    
196
    @Override
197
    public boolean isEnabled() {
198
        return true;
199
    }
200

    
201
    @Override
202
    public boolean isVisible() {
203
        return true;
204
    }
205

    
206
    @Override
207
    public boolean isVisible(String action) {
208
        IView view = getActiveView();
209
        FLyrVect activeLayer = getActiveLayer(view);
210

    
211
        if ("start-editing".equals(action)) {
212
            return ((view != null) && (activeLayer != null) && !activeLayer
213
                .isEditing());
214

    
215
        } else {
216
            return ((view != null) && (activeLayer != null) && activeLayer
217
                .isEditing());
218

    
219
        }
220
    }
221

    
222
    @Override
223
    public boolean isEnabled(String action) {
224

    
225
        IView vista = getActiveView();
226
        FLyrVect activeLayer = getActiveLayer(vista);
227

    
228
        if ("start-editing".equals(action)) {
229
            return (canBeEdited(activeLayer));
230

    
231
        } else if ("end-editing".equals(action)) {
232
            return activeLayer.isEditing();
233

    
234
        }
235

    
236
        return false;
237

    
238
    }
239

    
240
    @Override
241
    public boolean canQueryByAction() {
242
        return true;
243
    }
244

    
245
    private IView getActiveView() {
246
        ApplicationManager application = ApplicationLocator.getManager();
247
        IView view = (IView) application.getActiveComponent(ViewDocument.class);
248
        return view;
249
    }
250

    
251
    private boolean canBeEdited(FLyrVect layer) {
252
        if (layer != null && layer.isAvailable()) {
253

    
254
            boolean isWritable = layer.isWritable();
255
            boolean isNotTransformed =
256
                layer.getFeatureStore().getTransforms().isEmpty();
257

    
258
            return isWritable && isNotTransformed && !layer.isEditing();
259
        }
260

    
261
        return false;
262
    }
263

    
264
    private FLyrVect getActiveLayer(IView vista) {
265
        if (vista != null) {
266
            ViewDocument viewDocument = vista.getViewDocument();
267
            FLayer[] actives =
268
                viewDocument.getMapContext().getLayers().getActives();
269

    
270
            if ((actives.length == 1) && (actives[0] instanceof FLyrVect)) {
271
                return (FLyrVect) actives[0];
272
            }
273
        }
274
        return null;
275
    }
276

    
277
    @Override
278
    public void update(Observable observable, Object notification) {
279

    
280
        if (notification instanceof Notification){
281
            ApplicationManager appManager =
282
                ApplicationLocator.getManager();
283
            Notification n = (Notification)notification;
284
            if (n.getType().equalsIgnoreCase(EditingContext.CHANGE_SELECTED_TOOL_NOTIFICATION)){
285
                String name = (String)n.getValue();
286
                logger.trace("Changed selected tool to '{}'", name);
287
                PluginServices.getMainFrame().setSelectedTool(name);
288
                appManager.refreshMenusAndToolBars();
289

    
290
            } else if (n.getType().equalsIgnoreCase(EditingContext.REFRESH_TOOLS_NOTIFICATION)){
291
                appManager.refreshMenusAndToolBars();
292
            }
293
        }
294
    }
295

    
296
    private List<FLyrVect> getEditedLayers(){
297
        ApplicationManager application = ApplicationLocator.getManager();
298
        List<FLyrVect> editedLayers = new ArrayList<>();
299
        
300
        Project project = application.getCurrentProject();
301
        for( Document document : project.getDocuments(ViewManager.TYPENAME) ) {
302
            ViewDocument view = (ViewDocument) document;
303
            MapContext mapContext = view.getMapContext();
304
            if (mapContext != null) {
305
                FLayers layers = mapContext.getLayers();
306
                for (int j = 0; j < layers.getLayersCount(); j++) {
307
                    FLayer lyr = layers.getLayer(j);
308
                    if (lyr instanceof FLyrVect) {
309
                        FLyrVect layerVect = (FLyrVect) lyr;
310
                        if (layerVect.isEditing()) {
311
                            editedLayers.add(layerVect);
312
                        }
313
                    }
314
                }
315
            }
316
        }
317
        return editedLayers;
318
    }
319

    
320
    private List<IUnsavedData> getUnsavedData(List<FLyrVect> editedLayers){
321
        List<IUnsavedData> unsavedData = new ArrayList<>();
322
        for (FLyrVect editedLayer : editedLayers) {
323
            IUnsavedData unsavedDataLayer = new UnsavedLayer(this, editedLayer);
324
            unsavedData.add(unsavedDataLayer);
325
        }
326
        return unsavedData;
327

    
328
    }
329

    
330
    private static class UnsavedLayer extends UnsavedData {
331
        private final FLyrVect layer;
332

    
333
        public UnsavedLayer(IExtension extension, FLyrVect layer) {
334
            super(extension);
335
            this.layer = layer;
336
        }
337

    
338
        @Override
339
        public String getDescription() {
340
            return layer.getName();
341
        }
342

    
343
        @Override
344
        public String getResourceName() {
345
            return layer.getFeatureStore().getFullName();
346
        }
347

    
348
        @Override
349
        public boolean saveData() {
350
            FeatureStore featureStore = layer.getFeatureStore();
351
            if(featureStore.isEditing()){
352
                try {
353
                    featureStore.finishEditing();
354
                    return true;
355
                } catch (DataException e) {
356
                    throw new RuntimeException(e);
357
                }
358
            }
359
            return true;
360
        }
361
    }
362

    
363
    @Override
364
    public IExtensionStatus getStatus() {
365
        List<FLyrVect> editedLayers = getEditedLayers();
366
        final List<IUnsavedData> unsavedData = getUnsavedData(editedLayers);
367

    
368
        return new IExtensionStatus() {
369

    
370
            @Override
371
            public boolean hasUnsavedData() {
372
                if(unsavedData == null){
373
                    return false;
374
                }
375
                return !unsavedData.isEmpty();
376
            }
377

    
378
            @Override
379
            public boolean hasRunningProcesses() {
380
                return false;
381
            }
382

    
383
            @Override
384
            public IUnsavedData[] getUnsavedData() {
385
                if(unsavedData == null){
386
                    return null;
387
                }
388
                return unsavedData.toArray(new IUnsavedData[0]);
389
            }
390

    
391
            @Override
392
            public IMonitorableTask[] getRunningProcesses() {
393
                return null;
394
            }
395
        };
396
    }
397
}