Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / extension / ProjectExtension.java @ 47784

History | View | Annotate | Download (32.7 KB)

1 40558 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40558 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
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 40558 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * 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 40558 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
24
package org.gvsig.app.extension;
25
26
import java.awt.Component;
27 43506 jjdelcerro
import java.awt.geom.AffineTransform;
28
import java.awt.image.AffineTransformOp;
29
import java.awt.image.BufferedImage;
30 40435 jjdelcerro
import java.io.File;
31 43506 jjdelcerro
import java.io.IOException;
32 40435 jjdelcerro
import java.text.MessageFormat;
33
import java.util.ArrayList;
34
import java.util.Iterator;
35
import java.util.List;
36 42711 fdiaz
import java.util.Set;
37 40435 jjdelcerro
import java.util.prefs.Preferences;
38 43820 jjdelcerro
import java.util.zip.ZipFile;
39 40435 jjdelcerro
40
import javax.swing.JOptionPane;
41 46461 jjdelcerro
import javax.swing.SwingUtilities;
42 43439 jjdelcerro
import org.apache.commons.collections.CollectionUtils;
43 44088 omartinez
import org.apache.commons.io.FilenameUtils;
44 40435 jjdelcerro
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47 42200 fdiaz
48 41312 jjdelcerro
import org.gvsig.tools.util.ArrayUtils;
49 42200 fdiaz
50 41312 jjdelcerro
import org.apache.commons.lang.StringUtils;
51 42200 fdiaz
52 40435 jjdelcerro
import org.gvsig.andami.IconThemeHelper;
53
import org.gvsig.andami.Launcher;
54
import org.gvsig.andami.Launcher.TerminationProcess;
55
import org.gvsig.andami.PluginServices;
56 41312 jjdelcerro
import org.gvsig.andami.PluginsLocator;
57 43913 jjdelcerro
import org.gvsig.andami.PluginsManager;
58 41312 jjdelcerro
import org.gvsig.andami.actioninfo.ActionInfo;
59
import org.gvsig.andami.actioninfo.ActionInfoManager;
60 40435 jjdelcerro
import org.gvsig.andami.plugins.Extension;
61
import org.gvsig.andami.plugins.IExtension;
62
import org.gvsig.andami.plugins.status.IExtensionStatus;
63
import org.gvsig.andami.plugins.status.IUnsavedData;
64
import org.gvsig.andami.plugins.status.UnsavedData;
65
import org.gvsig.andami.ui.mdiManager.IWindow;
66
import org.gvsig.andami.ui.mdiManager.WindowInfo;
67
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
68 42711 fdiaz
import org.gvsig.app.ApplicationLocator;
69
import org.gvsig.app.ApplicationManager;
70 43506 jjdelcerro
import org.gvsig.app.gui.ProjectPreviewPanel;
71 40435 jjdelcerro
import org.gvsig.app.project.Project;
72
import org.gvsig.app.project.ProjectManager;
73
import org.gvsig.app.project.documents.gui.ProjectWindow;
74 43913 jjdelcerro
import org.gvsig.app.project.documents.gui.projectpanel.ProjectDocumentsPanelPageFactory;
75 40435 jjdelcerro
import org.gvsig.app.project.documents.view.ViewManager;
76 44237 jjdelcerro
import org.gvsig.filedialogchooser.FileDialogChooser;
77
import org.gvsig.filedialogchooser.FileDialogChooserManager;
78 40435 jjdelcerro
import org.gvsig.gui.beans.swing.JFileChooser;
79 43913 jjdelcerro
import org.gvsig.propertypage.PropertiesPageManager;
80 40435 jjdelcerro
import org.gvsig.tools.ToolsLocator;
81 41312 jjdelcerro
import org.gvsig.tools.dataTypes.DataTypes;
82 40435 jjdelcerro
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
83 45038 fdiaz
import org.gvsig.tools.folders.FoldersManager;
84 42711 fdiaz
import org.gvsig.tools.i18n.I18nManager;
85 45038 fdiaz
import org.gvsig.tools.locator.LocatorException;
86 43913 jjdelcerro
import org.gvsig.tools.util.ToolsUtilLocator;
87 40435 jjdelcerro
import org.gvsig.utils.GenericFileFilter;
88
import org.gvsig.utils.save.AfterSavingListener;
89
import org.gvsig.utils.save.BeforeSavingListener;
90
import org.gvsig.utils.save.SaveEvent;
91
import org.gvsig.utils.swing.threads.IMonitorableTask;
92
93
/**
94
 * Extension que proporciona controles para crear proyectos nuevos, abrirlos y
95 41076 jjdelcerro
 * guardarlos. Adem?s los tipos de tabla que soporta el proyecto son a?adidos en
96
 * esta clase.
97 42200 fdiaz
 *
98 40435 jjdelcerro
 */
99
public class ProjectExtension extends Extension implements IExtensionStatus {
100
101 44231 jjdelcerro
    private static final Logger LOG = LoggerFactory
102
            .getLogger(ProjectExtension.class);
103 40435 jjdelcerro
104 44231 jjdelcerro
    private static String projectPath = null;
105
    private ProjectWindow projectFrame;
106
    private Project p;
107
    private String lastSavePath;
108
    private WindowInfo seedProjectWindow;
109
    public static final String PROJECT_FILE_CHOOSER_ID = "PROJECT_FILECHOOSER_ID";
110
    /**
111
     * Use UTF-8 for encoding, as it can represent characters from any language.
112
     *
113
     * Another sensible option would be encoding =
114
     * System.getProperty("file.encoding"); but this would need some extra
115
     * testing.
116
     *
117
     * @deprecated see PersistentManager
118
     */
119
    public static String PROJECTENCODING = "UTF-8";
120 40435 jjdelcerro
121 45038 fdiaz
    private final List<BeforeSavingListener> beforeSavingListeners;
122 40435 jjdelcerro
123 45038 fdiaz
    private final List<AfterSavingListener> afterSavingListeners;
124 42200 fdiaz
125 45038 fdiaz
    public ProjectExtension() {
126
        this.afterSavingListeners = new ArrayList<>();
127
        this.beforeSavingListeners = new ArrayList<>();
128
    }
129
130 44231 jjdelcerro
    @Override
131
    public void initialize() {
132
        initializeDocumentActionsExtensionPoint();
133
        registerDocuments();
134
        registerIcons();
135 43913 jjdelcerro
136 44231 jjdelcerro
        PropertiesPageManager propertiesManager = ToolsUtilLocator.getPropertiesPageManager();
137
        propertiesManager.registerFactory(new ProjectDocumentsPanelPageFactory());
138
139
        File projectFile = getProjectFileFromArguments();
140
        if (projectFile != null) {
141
            // Posponemos la apertura del proyecto ya que en este momento
142
            // puede que no este inicializado algun plugin que precise el
143
            // proyecto para poderse cargar.
144
            PluginsLocator.getManager().addStartupTask(
145 41312 jjdelcerro
                    "Open project",
146 41314 jjdelcerro
                    new OpenInitialProjectTask(projectFile), true, 1000);
147 41312 jjdelcerro
        }
148 44231 jjdelcerro
    }
149 40435 jjdelcerro
150 44231 jjdelcerro
    private void registerIcons() {
151
        IconThemeHelper.registerIcon("action", "application-project-new", this);
152
        IconThemeHelper
153
                .registerIcon("action", "application-project-open", this);
154
        IconThemeHelper
155
                .registerIcon("action", "application-project-save", this);
156
        IconThemeHelper.registerIcon("action", "application-project-save-as",
157
                this);
158 40435 jjdelcerro
159 44231 jjdelcerro
        IconThemeHelper.registerIcon("project", "project-icon", this);
160 46301 fdiaz
        IconThemeHelper.registerIcon("project", "temporary-table-icon", this);
161 44231 jjdelcerro
    }
162 40435 jjdelcerro
163 44231 jjdelcerro
    /**
164
     * Returns the file to be opened or null if no parameter or file does not
165
     * exist
166
     *
167
     * @return
168
     */
169
    private File getProjectFileFromArguments() {
170
        String[] theArgs = PluginServices.getArguments();
171
        if (theArgs.length < 3) {
172
            // application-name and extensions-folder are fixed arguments
173
            return null;
174 42200 fdiaz
        }
175 44231 jjdelcerro
        String lastArg = theArgs[theArgs.length - 1];
176
        if (StringUtils.isEmpty(lastArg)) {
177
            return null;
178
        }
179
        if (lastArg.startsWith("-")) {
180
            // Args starts with "-" are flags
181
            return null;
182
        }
183
        if (!lastArg.toLowerCase().endsWith(Project.FILE_EXTENSION.toLowerCase())) {
184
            LOG.info("Do not open project file, does not have the expected extension '"
185
                    + Project.FILE_EXTENSION + "' (" + lastArg + ").");
186
            return null;
187
        }
188
        File projectFile = new File(lastArg);
189
        if (!projectFile.exists()) {
190
            LOG.info("Do not open project file, '" + projectFile.getAbsolutePath() + "' do not exist.");
191
            return null;
192
        }
193
        return projectFile;
194
    }
195 41314 jjdelcerro
196 44231 jjdelcerro
    private class OpenInitialProjectTask implements Runnable {
197
198 45038 fdiaz
        private final File projectFile;
199 44231 jjdelcerro
200
        public OpenInitialProjectTask(File projectFile) {
201
            this.projectFile = projectFile;
202
        }
203
204
        @Override
205
        public void run() {
206
            if (this.projectFile == null) {
207
                return;
208 41314 jjdelcerro
            }
209 44231 jjdelcerro
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
210
            ActionInfo action = actionManager.getAction("application-project-open");
211
            action.execute(this.projectFile);
212 41312 jjdelcerro
        }
213 44231 jjdelcerro
    }
214 40435 jjdelcerro
215 44231 jjdelcerro
    public ProjectWindow getProjectFrame() {
216
        if (projectFrame == null) {
217
            projectFrame = new ProjectWindow();
218
        }
219
        return projectFrame;
220
    }
221 40435 jjdelcerro
222 44231 jjdelcerro
    /**
223
     * Muestra la ventana con el gestor de proyectos.
224
     */
225
    public void showProjectWindow() {
226
        if (seedProjectWindow != null) {
227
            if (seedProjectWindow.isClosed()) {
228
                // if it was closed, we just don't open the window now
229
                seedProjectWindow.setClosed(false);
230
                return;
231
            }
232
            WindowInfo winProps = seedProjectWindow;
233
            seedProjectWindow = null;
234
            PluginServices.getMDIManager().addWindow(getProjectFrame());
235
            PluginServices.getMDIManager().changeWindowInfo(getProjectFrame(),
236
                    winProps);
237
        } else {
238
            PluginServices.getMDIManager().addWindow(getProjectFrame());
239
        }
240
    }
241 40435 jjdelcerro
242 44231 jjdelcerro
    /**
243
     * Muestra la ventana con el gestor de proyectos, con las propiedades de
244
     * ventana especificadas.
245 45038 fdiaz
     * @param wi
246 44231 jjdelcerro
     */
247
    public void showProjectWindow(WindowInfo wi) {
248
        seedProjectWindow = wi;
249
        showProjectWindow();
250
    }
251 40435 jjdelcerro
252 44231 jjdelcerro
    /**
253
     * Guarda el proyecto actual en disco.
254
     */
255
    private boolean saveProject() {
256 45038 fdiaz
        boolean saved;
257 44231 jjdelcerro
        if (projectPath == null) {
258
            saved = saveAsProject(null);
259
        } else {
260
            long t1, t2;
261
            t1 = System.currentTimeMillis();
262
            saved = writeProject(new File(projectPath), p, false);
263
            t2 = System.currentTimeMillis();
264
            PluginServices.getLogger().info(
265
                    "Project saved. " + (t2 - t1) + " miliseconds");
266
            getProjectFrame().setProject(p);
267
        }
268
        return saved;
269
    }
270 40435 jjdelcerro
271 44231 jjdelcerro
    private boolean saveAsProject(File file) {
272
        boolean saved = false;
273 40435 jjdelcerro
274 44231 jjdelcerro
        if (lastSavePath == null) {
275
            lastSavePath = projectPath;
276
        }
277 40435 jjdelcerro
278 44231 jjdelcerro
        if (file == null) {
279 44237 jjdelcerro
            FileDialogChooserManager fileDialogChooserManager = ToolsUtilLocator.getFileDialogChooserManager();
280
            FileDialogChooser jfc = fileDialogChooserManager.create(PROJECT_FILE_CHOOSER_ID);
281 45038 fdiaz
            if (lastSavePath == null) {
282
                jfc.setCurrentDirectory(getPreferredProjectsFolder());
283
            } else {
284
                jfc.setCurrentDirectory(new File(lastSavePath));
285
            }
286 44231 jjdelcerro
            jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
287 42200 fdiaz
288 44231 jjdelcerro
            GenericFileFilter projExtensionFilter = new GenericFileFilter(
289
                    Project.FILE_EXTENSION, MessageFormat.format(PluginServices
290
                            .getText(this, "tipo_fichero_proyecto"),
291
                            Project.FILE_EXTENSION));
292
            jfc.addChoosableFileFilter(projExtensionFilter);
293
            jfc.setFileFilter(projExtensionFilter);
294 45038 fdiaz
295 44231 jjdelcerro
            if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
296
                return saved;
297
            }
298
            file = jfc.getSelectedFile();
299
        }
300 40435 jjdelcerro
301 44231 jjdelcerro
        if (!(file.getPath().toLowerCase().endsWith(Project.FILE_EXTENSION
302
                .toLowerCase()))) {
303
            file = new File(file.getPath() + Project.FILE_EXTENSION);
304
        }
305
        saved = writeProject(file, p);
306
        String filePath = file.getAbsolutePath();
307 45038 fdiaz
        lastSavePath = FilenameUtils.getPath(filePath);
308 40435 jjdelcerro
309 44231 jjdelcerro
        getProjectFrame().setProject(p);
310
        return saved;
311
    }
312 40435 jjdelcerro
313 44231 jjdelcerro
    /**
314
     * Checks whether the project and related unsaved data is modified, and
315
     * allows the user to save it.
316
     *
317
     * @return true if the data has been correctly saved, false otherwise
318
     */
319
    private boolean askSave() {
320
        if (p != null && p.hasChanged()) {
321
            TerminationProcess process = Launcher.getTerminationProcess();
322
            UnsavedDataPanel panel = process.getUnsavedDataPanel();
323
            panel.setHeaderText(PluginServices.getText(this,
324
                    "_Select_resources_to_save_before_closing_current_project"));
325
            panel.setAcceptText(
326
                    PluginServices.getText(this, "save_resources"),
327
                    PluginServices
328
                            .getText(this,
329
                                    "Save_the_selected_resources_and_close_current_project"));
330
            panel.setCancelText(PluginServices.getText(this, "Cancel"),
331
                    PluginServices.getText(this, "Return_to_current_project"));
332
            int closeCurrProj;
333
            try {
334
                closeCurrProj = process.manageUnsavedData();
335
                if (closeCurrProj == JOptionPane.NO_OPTION) {
336
                    // the user chose to return to current project
337
                    return false;
338
                }
339
            } catch (Exception e) {
340
                LOG.error("Some data can not be saved", e);
341
            }
342
        }
343
        return true;
344
    }
345 40435 jjdelcerro
346 44231 jjdelcerro
    @Override
347
    public void execute(String command) {
348
        this.execute(command, null);
349
    }
350 42200 fdiaz
351 44231 jjdelcerro
    @Override
352 43293 fdiaz
    public void execute(String actionCommand, Object[] args) {
353 46461 jjdelcerro
        ApplicationManager application = ApplicationLocator.getApplicationManager();
354
        I18nManager i18n = ToolsLocator.getI18nManager();
355
356 45038 fdiaz
        switch (actionCommand) {
357
            case "application-project-new":
358
                if (!askSave()) {
359 43293 fdiaz
                    return;
360 45038 fdiaz
                }   projectPath = null;
361 46461 jjdelcerro
                application.getUIManager().closeAllWindows();
362 45038 fdiaz
                setProject(ProjectManager.getInstance().createProject());
363
                showProjectWindow();
364 46461 jjdelcerro
                application.getMainFrame().setTitle(i18n.getTranslation("sin_titulo"));
365 45038 fdiaz
                break;
366
            case "application-project-open":
367
                if (!askSave()) {
368
                    return;
369 46906 fdiaz
                }
370 45038 fdiaz
                File projectFile = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
371
                if (projectFile != null && !projectFile.exists()) {
372
                    LOG.warn("Can't load project '" + projectFile.getAbsolutePath() + "', file not exist.");
373
                    projectFile = null;
374
                }   if (projectFile == null) {
375
                    FileDialogChooserManager fileDialogChooserManager = ToolsUtilLocator.getFileDialogChooserManager();
376
                    FileDialogChooser jfc = fileDialogChooserManager.create(PROJECT_FILE_CHOOSER_ID);
377
                    if (lastSavePath == null) {
378
                        jfc.setCurrentDirectory(getPreferredProjectsFolder());
379
                    } else {
380
                        jfc.setCurrentDirectory(new File(lastSavePath));
381
                    }
382
                    ProjectPreviewPanel preview = new ProjectPreviewPanel();
383
                    jfc.setAccessory(preview);
384
                    jfc.addPropertyChangeListener(preview);
385
386
                    GenericFileFilter projExtensionFilter
387 46461 jjdelcerro
                            = new GenericFileFilter(Project.FILE_EXTENSION, i18n.getTranslation("tipo_fichero_proyecto"));
388 45038 fdiaz
                    jfc.addChoosableFileFilter(projExtensionFilter);
389
                    GenericFileFilter bakExtensionFilter
390 46461 jjdelcerro
                            = new GenericFileFilter(Project.FILE_BAK, i18n.getTranslation("tipo_fichero_proyecto_bak"));
391 45038 fdiaz
                    jfc.addChoosableFileFilter(bakExtensionFilter);
392
                    jfc.setFileFilter(projExtensionFilter);
393
394 46461 jjdelcerro
                    if (jfc.showOpenDialog((Component) application.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
395 45038 fdiaz
                        return;
396
                    }
397
                    projectFile = jfc.getSelectedFile();
398 46461 jjdelcerro
                }
399 46906 fdiaz
                setProject(ProjectManager.getInstance().createProject());
400 46461 jjdelcerro
                loadProject(projectFile);
401 45038 fdiaz
                break;
402 46461 jjdelcerro
403 45038 fdiaz
            case "application-project-save":
404
                // saveProject();
405
                try {
406
                    Launcher.manageUnsavedData("there_are_unsaved_resources");
407
                } catch (Exception e) {
408
                    LOG.warn("Can't manage unsaved data", e);
409
                }   break;
410
            case "application-project-save-as":
411
                File file = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
412
                saveAsProject(file);
413
                break;
414
            default:
415
                break;
416 43293 fdiaz
        }
417 40435 jjdelcerro
418 43293 fdiaz
    }
419 46461 jjdelcerro
420
    private void loadProject(File projectFile) {
421
        ApplicationManager application = ApplicationLocator.getApplicationManager();
422
        application.getUIManager().closeAllWindows();
423
        PluginsLocator.getActionInfoManager().setAllDisabled(true);
424
        application.refreshMenusAndToolBars();
425
        Thread task = new Thread(() -> {
426
            Project o = readProject(projectFile);
427
            SwingUtilities.invokeLater(new Runnable() {
428
                @Override
429
                public void run() {
430 47509 jjdelcerro
                    try {
431
                        if ("bak".equals(FilenameUtils.getExtension(projectFile.getAbsolutePath()))) {
432
                            setPath(null);
433
                        } else {
434
                            setPath(projectFile.getAbsolutePath());
435
                        }
436
                        if (o != null) {
437
                            setProject(o);
438
                        }
439
                        getProjectFrame().setProject(p);
440
                        application.getMainFrame().setTitle(projectFile.getName());
441
                    } finally {
442
                        PluginsLocator.getActionInfoManager().setAllDisabled(false);
443
                        application.message("", JOptionPane.INFORMATION_MESSAGE);
444
                        application.refreshMenusAndToolBars();
445 46461 jjdelcerro
                    }
446
                }
447
            });
448
        }, "LoadProject");
449
        task.start();
450
    }
451 40435 jjdelcerro
452 45038 fdiaz
    private File getPreferredProjectsFolder() throws LocatorException {
453
        Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
454 47521 jjdelcerro
//        FoldersManager folderManager = ToolsLocator.getFoldersManager();
455 45038 fdiaz
        String v;
456
457 47521 jjdelcerro
//        v = prefs.get(InitializeApplicationExtension.PROJECTS_FOLDER_PROPERTY_NAME, folderManager.getHome().getAbsolutePath());
458
        v = prefs.get(InitializeApplicationExtension.PROJECTS_FOLDER_PROPERTY_NAME, null);
459
        if( StringUtils.isBlank(v) ) {
460
            return null;
461
        }
462 45038 fdiaz
        return new File(v);
463
    }
464
465 41217 jldominguez
    private void createEmptyProject() {
466
        setProject(ProjectManager.getInstance().createProject());
467
        p.setName(PluginServices.getText(this, "untitled"));
468
        p.setModified(false);
469
        PluginServices.getMainFrame().setTitle(
470
                PluginServices.getText(this, "sin_titulo"));
471
        setProject(p);
472
        showProjectWindow();
473
    }
474
475 43913 jjdelcerro
    @Override
476 41217 jldominguez
    public void postInitialize() {
477 43913 jjdelcerro
        PluginsManager pluginsManager = PluginsLocator.getManager();
478 45038 fdiaz
        pluginsManager.addStartupTask("createEmptyProject", () -> {
479
            createEmptyProject();
480 44231 jjdelcerro
        },
481
                true,
482 43942 jjdelcerro
                1000
483 43913 jjdelcerro
        );
484 42200 fdiaz
    }
485
486 44231 jjdelcerro
    /**
487
     * Escribe el proyecto en XML.
488
     *
489
     * @param file Fichero.
490
     * @param p Proyecto.
491 45038 fdiaz
     * @return
492 44231 jjdelcerro
     */
493
    public boolean writeProject(File file, Project p) {
494
        return writeProject(file, p, true);
495
    }
496 42200 fdiaz
497 43820 jjdelcerro
    /**
498 44231 jjdelcerro
     * Escribe el proyecto en disco. Pero permite decidir si se pide
499
     * confirmaci?n para sobreescribir
500 43820 jjdelcerro
     *
501
     * @param file Fichero.
502
     * @param p Proyecto.
503
     * @param askConfirmation boolean
504
     * @return
505
     */
506 44231 jjdelcerro
    public boolean writeProject(File file, Project p, boolean askConfirmation) {
507 43820 jjdelcerro
        I18nManager i18n = ToolsLocator.getI18nManager();
508
        ApplicationManager application = ApplicationLocator.getManager();
509
        if (askConfirmation && file.exists()) {
510
            int resp = application.confirmDialog(
511 44231 jjdelcerro
                    i18n.getTranslation("fichero_ya_existe_seguro_desea_guardarlo"),
512
                    i18n.getTranslation("guardar"),
513
                    JOptionPane.YES_NO_OPTION,
514
                    JOptionPane.QUESTION_MESSAGE,
515 43820 jjdelcerro
                    "Overwrite_project_file"
516
            );
517
            if (resp != JOptionPane.YES_OPTION) {
518
                return false;
519
            }
520
        }
521 44231 jjdelcerro
        LOG.info("Writing project '" + file.getAbsolutePath() + "'.");
522 43820 jjdelcerro
        try {
523 44231 jjdelcerro
            fireBeforeSavingFileEvent(new SaveEvent(this, SaveEvent.BEFORE_SAVING, file));
524 43506 jjdelcerro
            BufferedImage img = ApplicationLocator.getManager().getUIManager().getImagePreview();
525
            img = scale(img, 0.40);
526 44231 jjdelcerro
            p.saveState(file, img);
527 43820 jjdelcerro
528
            PluginServices.getMainFrame().setTitle(file.getName());
529
            setPath(file.toString());
530 40435 jjdelcerro
531 45038 fdiaz
        } catch (LocatorException e) {
532 43820 jjdelcerro
            application.messageDialog(
533 44231 jjdelcerro
                    i18n.getTranslation("_Problems_saving_the_project_XnlX_It_is_possible_that_this_was_not_saved_properly_and_can_not_be_loaded_again"),
534
                    null,
535
                    i18n.getTranslation("guardar"),
536
                    JOptionPane.ERROR_MESSAGE,
537 43820 jjdelcerro
                    "Problems_saving_the_project"
538
            );
539 44231 jjdelcerro
            LOG.warn("Error writing project '" + file.getAbsolutePath() + "'.", e);
540 43820 jjdelcerro
            return false;
541 44231 jjdelcerro
        }
542
        LOG.warn("Wrote project '" + file.getAbsolutePath() + "'.");
543 43820 jjdelcerro
        return true;
544
    }
545 40435 jjdelcerro
546 43820 jjdelcerro
    boolean isValidZIP(final File file) {
547
        ZipFile zipfile = null;
548
        try {
549
            zipfile = new ZipFile(file);
550
            return true;
551
        } catch (IOException e) {
552
            return false;
553
        } finally {
554
            try {
555
                if (zipfile != null) {
556
                    zipfile.close();
557
                }
558
            } catch (IOException e) {
559
            }
560
        }
561
    }
562 40435 jjdelcerro
563 43506 jjdelcerro
    private BufferedImage scale(BufferedImage before, double factor) {
564 44231 jjdelcerro
        int w = (int) (before.getWidth() * factor);
565
        int h = (int) (before.getHeight() * factor);
566 43506 jjdelcerro
        BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
567
        AffineTransform at = new AffineTransform();
568
        at.scale(factor, factor);
569
        AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
570 44231 jjdelcerro
        after = scaleOp.filter(before, after);
571 43506 jjdelcerro
        return after;
572
    }
573 40435 jjdelcerro
574 44231 jjdelcerro
    public Project readProject(String path) {
575
        Project project = ProjectManager.getInstance().createProject();
576 40435 jjdelcerro
577 44231 jjdelcerro
        project.loadState(new File(path));
578
        return (Project) project;
579
    }
580 40435 jjdelcerro
581 44231 jjdelcerro
    /**
582
     * Lee del XML el proyecto.<br>
583
     * <br>
584
     *
585
     * Reads the XML of the project.<br>
586
     * It returns a project object holding all needed info that is not linked to
587
     * the Project Dialog. <br>
588
     * In case you want the project to be linked to the window you must set this
589
     * object to the extension:<br>
590
     *
591
     * <b>Example:</b><br>
592
     *
593
     * ...<br>
594
     * .
595
     * ..<br>
596
     * Project p = ProjectExtension.readProject(projectFile);<br>
597
     * ProjectExtension.setProject(p); ...<br>
598
     * .
599
     * ..<br>
600
     *
601
     * @param file Fichero.
602
     *
603
     * @return Project
604
     *
605
     */
606
    public Project readProject(File file) {
607
        Project project = ProjectManager.getInstance().createProject();
608
609
        project.loadState(file);
610
        Set<String> unloadedObjects = project.getUnloadedObjects();
611 43439 jjdelcerro
        List<Exception> errors = project.getLoadErrors();
612 44231 jjdelcerro
613
        if (!CollectionUtils.isEmpty(unloadedObjects)) {
614
            StringBuilder builder = new StringBuilder();
615
            builder.append("Unloaded elements loading the project:\n");
616
            Iterator<String> it = unloadedObjects.iterator();
617
            while (it.hasNext()) {
618 42711 fdiaz
                builder.append("\t");
619 44231 jjdelcerro
                builder.append(it.next());
620
                builder.append("\n");
621
            }
622 42711 fdiaz
623 44231 jjdelcerro
            LOG.warn(builder.toString());
624 43439 jjdelcerro
        }
625 44231 jjdelcerro
        if (!CollectionUtils.isEmpty(unloadedObjects) || !CollectionUtils.isEmpty(errors)) {
626
            ApplicationManager application = ApplicationLocator.getManager();
627
            I18nManager i18nManager = ToolsLocator.getI18nManager();
628 42711 fdiaz
629 44231 jjdelcerro
            application.messageDialog(
630
                    i18nManager.getTranslation("_some_project_elements_could_not_be_loaded") + "\n"
631
                    + i18nManager.getTranslation("_maybe_you_need_to_install_any_plugins") + "\n"
632
                    + i18nManager.getTranslation("_Recovered_data_may_be_corrupted") + "\n\n"
633
                    + i18nManager.getTranslation("_see_error_log_for_more_information"),
634
                    i18nManager.getTranslation("warning"),
635
                    JOptionPane.WARNING_MESSAGE);
636 42711 fdiaz
637 44231 jjdelcerro
        } else {
638
639 43439 jjdelcerro
        }
640 44231 jjdelcerro
        return (Project) project;
641
    }
642 40435 jjdelcerro
643 44231 jjdelcerro
    /**
644
     * Devuelve el proyecto.
645
     *
646
     * @return Proyecto.
647
     */
648
    public Project getProject() {
649
        return p;
650
    }
651 40435 jjdelcerro
652 44231 jjdelcerro
    /**
653
     * @see org.gvsig.andami.plugins.IExtension#isEnabled()
654
     */
655 45038 fdiaz
    @Override
656 44231 jjdelcerro
    public boolean isEnabled() {
657
        return true;
658
    }
659 40435 jjdelcerro
660 44231 jjdelcerro
    /**
661
     * @see org.gvsig.andami.plugins.IExtension#isVisible()
662
     */
663 45038 fdiaz
    @Override
664 44231 jjdelcerro
    public boolean isVisible() {
665
        return true;
666
    }
667 40435 jjdelcerro
668 44231 jjdelcerro
    /**
669
     * Sets the project
670
     *
671
     * @param p
672
     */
673
    public void setProject(Project p) {
674
        this.p = p;
675
        getProjectFrame().setProject(p);
676
    }
677 40435 jjdelcerro
678 44231 jjdelcerro
    private void registerDocuments() {
679
        ViewManager.register();
680
    }
681 40435 jjdelcerro
682 44231 jjdelcerro
    private void initializeDocumentActionsExtensionPoint() {
683
        ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
684
        epMan.add(
685
                "DocumentActions_View",
686
                "Context menu options of the view document list"
687
                + " in the project window "
688
                + "(register instances of "
689
                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
690
    }
691 40435 jjdelcerro
692 44231 jjdelcerro
    public static String getPath() {
693
        return projectPath;
694
    }
695 40435 jjdelcerro
696 44231 jjdelcerro
    public static void setPath(String path) {
697
        projectPath = path;
698
    }
699 40435 jjdelcerro
700 44231 jjdelcerro
    public IWindow getProjectWindow() {
701
        return getProjectFrame();
702
    }
703 40435 jjdelcerro
704 44231 jjdelcerro
    @Override
705
    public IExtensionStatus getStatus() {
706
        return this;
707
    }
708 40435 jjdelcerro
709 44231 jjdelcerro
    @Override
710
    public boolean hasUnsavedData() {
711
        return p.hasChanged();
712
    }
713 40435 jjdelcerro
714 44231 jjdelcerro
    @Override
715
    public IUnsavedData[] getUnsavedData() {
716
        if (hasUnsavedData()) {
717
            UnsavedProject data = new UnsavedProject(this);
718
            IUnsavedData[] dataArray = {data};
719
            return dataArray;
720
        } else {
721
            return null;
722
        }
723
    }
724 40435 jjdelcerro
725 44231 jjdelcerro
    /**
726
     * Implements the IUnsavedData interface to show unsaved projects in the
727
     * Unsavad Data dialog.
728
     *
729
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
730
     */
731
    public class UnsavedProject extends UnsavedData {
732 40435 jjdelcerro
733 44231 jjdelcerro
        public UnsavedProject(IExtension extension) {
734
            super(extension);
735
        }
736 40435 jjdelcerro
737 44231 jjdelcerro
        @Override
738
        public String getDescription() {
739
            if (getPath() == null) {
740
                return PluginServices.getText(ProjectExtension.this,
741
                        "Unnamed_new_gvsig_project_");
742
            } else {
743
                return PluginServices.getText(ProjectExtension.this,
744
                        "Modified_project_");
745
            }
746
        }
747 40435 jjdelcerro
748 44231 jjdelcerro
        @Override
749
        public String getResourceName() {
750
            if (getPath() == null) {
751 45679 jjdelcerro
                return PluginServices.getText(ProjectExtension.this, "_Project_not_saved");
752 44231 jjdelcerro
            } else {
753
                return getPath();
754
            }
755 40435 jjdelcerro
756 44231 jjdelcerro
        }
757 40435 jjdelcerro
758 44088 omartinez
        @Override
759 44231 jjdelcerro
        public boolean saveData() {
760
            return saveProject();
761
        }
762 40435 jjdelcerro
763 44088 omartinez
        @Override
764 44231 jjdelcerro
        public String getIcon() {
765
            return "project-icon";
766
        }
767
    }
768 40435 jjdelcerro
769 44231 jjdelcerro
    @Override
770
    public IMonitorableTask[] getRunningProcesses() {
771
        // TODO Auto-generated method stub
772
        return null;
773
    }
774 40435 jjdelcerro
775 44231 jjdelcerro
    @Override
776
    public boolean hasRunningProcesses() {
777
        // TODO Auto-generated method stub
778
        return false;
779
    }
780 40435 jjdelcerro
781 44231 jjdelcerro
    /**
782
     * Adds the specified before saving listener to receive "before saving file
783
     * events" from this component. If l is null, no exception is thrown and no
784
     * action is performed.
785
     *
786
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
787
     *
788
     * @param l the before saving listener.
789
     * @see SaveEvent
790
     * @see BeforeSavingListener
791
     * @see #removeListener(BeforeSavingListener)
792
     * @see #getBeforeSavingListeners
793
     */
794
    public synchronized void addListener(BeforeSavingListener l) {
795
        if (l == null) {
796
            return;
797
        }
798
        if (!this.beforeSavingListeners.contains(l)) {
799
            this.beforeSavingListeners.add(l);
800
        }
801
    }
802 40435 jjdelcerro
803 44231 jjdelcerro
    /**
804
     * Adds the specified after saving listener to receive "after saving file
805
     * events" from this component. If l is null, no exception is thrown and no
806
     * action is performed.
807
     *
808
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
809
     *
810
     * @param l the after saving listener.
811
     * @see SaveEvent
812
     * @see AfterSavingListener
813
     * @see #removeListener(AfterSavingListener)
814
     * @see #getAfterSavingListeners()
815
     */
816
    public synchronized void addListener(AfterSavingListener l) {
817
        if (l == null) {
818
            return;
819
        }
820 40435 jjdelcerro
821 44231 jjdelcerro
        if (!this.afterSavingListeners.contains(l)) {
822
            this.afterSavingListeners.add(l);
823
        }
824 40435 jjdelcerro
825 44231 jjdelcerro
    }
826 40435 jjdelcerro
827 44231 jjdelcerro
    /**
828
     * Returns an array of all the before saving listeners registered on this
829
     * component.
830
     *
831
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
832
     *
833
     * @return all of this component's <code>BeforeSavingListener</code>s or an
834
     * empty array if no key listeners are currently registered
835
     *
836
     * @see #addBeforeSavingListener(BeforeSavingListener)
837
     * @see #removeBeforeSavingListener(BeforeSavingListener)
838
     */
839
    public synchronized BeforeSavingListener[] getBeforeSavingListeners() {
840
        return this.beforeSavingListeners
841
                .toArray(new BeforeSavingListener[]{});
842
    }
843 40435 jjdelcerro
844 44231 jjdelcerro
    /**
845
     * Returns an array of all the after saving listeners registered on this
846
     * component.
847
     *
848
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
849
     *
850
     * @return all of this component's <code>AfterSavingListener</code>s or an
851
     * empty array if no key listeners are currently registered
852
     *
853
     * @see #addAfterSavingListener(AfterSavingListener)
854
     * @see #removeAfterSavingListener
855
     */
856
    public synchronized AfterSavingListener[] getAfterSavingListeners() {
857
        return this.afterSavingListeners.toArray(new AfterSavingListener[]{});
858 40435 jjdelcerro
859 44231 jjdelcerro
    }
860 40435 jjdelcerro
861 44231 jjdelcerro
    /**
862
     * Removes the specified before saving listener so that it no longer
863
     * receives save file events from this component. This method performs no
864
     * function, nor does it throw an exception, if the listener specified by
865
     * the argument was not previously added to this component. If listener
866
     * <code>l</code> is <code>null</code>, no exception is thrown and no action
867
     * is performed.
868
     *
869
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
870
     *
871
     * @param l the before saving listener
872
     * @see SaveEvent
873
     * @see BeforeSavingListener
874
     * @see #addListener(BeforeSavingListener)
875
     * @see #getBeforeSavingListeners()
876
     */
877
    public synchronized void removeListener(BeforeSavingListener l) {
878
        if (l == null) {
879
            return;
880
        }
881 41076 jjdelcerro
882 44231 jjdelcerro
        this.beforeSavingListeners.remove(l);
883
    }
884 41076 jjdelcerro
885 44231 jjdelcerro
    /**
886
     * Removes the specified after saving listener so that it no longer receives
887
     * save file events from this component. This method performs no function,
888
     * nor does it throw an exception, if the listener specified by the argument
889
     * was not previously added to this component. If listener <code>l</code> is
890
     * <code>null</code>, no exception is thrown and no action is performed.
891
     *
892
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
893
     *
894
     * @param l the after saving listener
895
     * @see SaveEvent
896
     * @see AfterSavingListener
897
     * @see #addListener(AfterSavingListener)
898
     * @see #getAfterSavingListeners()
899
     */
900
    public synchronized void removeListener(AfterSavingListener l) {
901
        if (l == null) {
902
            return;
903
        }
904 41076 jjdelcerro
905 44231 jjdelcerro
        this.afterSavingListeners.remove(l);
906
    }
907 41076 jjdelcerro
908 44231 jjdelcerro
    /**
909
     * Reports a before saving file event.
910
     *
911
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
912
     *
913
     * @param evt the before saving file event
914
     */
915
    protected void fireBeforeSavingFileEvent(SaveEvent evt) {
916
        if ((evt.getID() != SaveEvent.BEFORE_SAVING) || (evt.getFile() == null)) {
917
            return;
918
        }
919 41076 jjdelcerro
920 44231 jjdelcerro
        Iterator<BeforeSavingListener> iter = this.beforeSavingListeners
921
                .iterator();
922 41076 jjdelcerro
923 44231 jjdelcerro
        while (iter.hasNext()) {
924
            iter.next().beforeSaving(evt);
925
        }
926
    }
927 41076 jjdelcerro
928 44231 jjdelcerro
    /**
929
     * Reports a after saving file event.
930
     *
931
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
932
     *
933
     * @param evt the after saving file event
934
     */
935
    protected void fireAfterSavingFileEvent(SaveEvent evt) {
936
        if ((evt.getID() != SaveEvent.AFTER_SAVING) || (evt.getFile() == null)) {
937
            return;
938
        }
939
        Iterator<AfterSavingListener> iter = this.afterSavingListeners
940
                .iterator();
941
942
        while (iter.hasNext()) {
943
            iter.next().afterSaving(evt);
944
        }
945
946
    }
947 40435 jjdelcerro
}