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

History | View | Annotate | Download (30.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 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 3
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.app.extension;
25

    
26
import java.awt.Component;
27
import java.awt.geom.AffineTransform;
28
import java.awt.image.AffineTransformOp;
29
import java.awt.image.BufferedImage;
30
import java.io.File;
31
import java.io.IOException;
32
import java.text.MessageFormat;
33
import java.util.ArrayList;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Set;
37
import java.util.prefs.Preferences;
38
import java.util.zip.ZipFile;
39

    
40
import javax.swing.JOptionPane;
41
import org.apache.commons.collections.CollectionUtils;
42
import org.apache.commons.io.FilenameUtils;
43

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

    
47
import org.gvsig.tools.util.ArrayUtils;
48

    
49
import org.apache.commons.lang.StringUtils;
50

    
51
import org.gvsig.andami.IconThemeHelper;
52
import org.gvsig.andami.Launcher;
53
import org.gvsig.andami.Launcher.TerminationProcess;
54
import org.gvsig.andami.PluginServices;
55
import org.gvsig.andami.PluginsLocator;
56
import org.gvsig.andami.PluginsManager;
57
import org.gvsig.andami.actioninfo.ActionInfo;
58
import org.gvsig.andami.actioninfo.ActionInfoManager;
59
import org.gvsig.andami.plugins.Extension;
60
import org.gvsig.andami.plugins.IExtension;
61
import org.gvsig.andami.plugins.status.IExtensionStatus;
62
import org.gvsig.andami.plugins.status.IUnsavedData;
63
import org.gvsig.andami.plugins.status.UnsavedData;
64
import org.gvsig.andami.ui.mdiManager.IWindow;
65
import org.gvsig.andami.ui.mdiManager.WindowInfo;
66
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
67
import org.gvsig.app.ApplicationLocator;
68
import org.gvsig.app.ApplicationManager;
69
import org.gvsig.app.gui.ProjectPreviewPanel;
70
import org.gvsig.app.project.Project;
71
import org.gvsig.app.project.ProjectManager;
72
import org.gvsig.app.project.documents.gui.ProjectWindow;
73
import org.gvsig.app.project.documents.gui.projectpanel.ProjectDocumentsPanelPageFactory;
74
import org.gvsig.app.project.documents.view.ViewManager;
75
import org.gvsig.gui.beans.swing.JFileChooser;
76
import org.gvsig.propertypage.PropertiesPageManager;
77
import org.gvsig.tools.ToolsLocator;
78
import org.gvsig.tools.dataTypes.DataTypes;
79
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
80
import org.gvsig.tools.i18n.I18nManager;
81
import org.gvsig.tools.util.ToolsUtilLocator;
82
import org.gvsig.utils.GenericFileFilter;
83
import org.gvsig.utils.save.AfterSavingListener;
84
import org.gvsig.utils.save.BeforeSavingListener;
85
import org.gvsig.utils.save.SaveEvent;
86
import org.gvsig.utils.swing.threads.IMonitorableTask;
87

    
88
/**
89
 * Extension que proporciona controles para crear proyectos nuevos, abrirlos y
90
 * guardarlos. Adem?s los tipos de tabla que soporta el proyecto son a?adidos en
91
 * esta clase.
92
 *
93
 */
94
public class ProjectExtension extends Extension implements IExtensionStatus {
95

    
96
    private static final Logger LOG = LoggerFactory
97
            .getLogger(ProjectExtension.class);
98

    
99
    private static String projectPath = null;
100
    private ProjectWindow projectFrame;
101
    private Project p;
102
    private String lastSavePath;
103
    private WindowInfo seedProjectWindow;
104
    public static final String PROJECT_FILE_CHOOSER_ID = "PROJECT_FILECHOOSER_ID";
105
    /**
106
     * Use UTF-8 for encoding, as it can represent characters from any language.
107
     *
108
     * Another sensible option would be encoding =
109
     * System.getProperty("file.encoding"); but this would need some extra
110
     * testing.
111
     *
112
     * @deprecated see PersistentManager
113
     */
114
    public static String PROJECTENCODING = "UTF-8";
115

    
116
    private List<BeforeSavingListener> beforeSavingListeners = new ArrayList<BeforeSavingListener>();
117

    
118
    private List<AfterSavingListener> afterSavingListeners = new ArrayList<AfterSavingListener>();
119

    
120
    @Override
121
    public void initialize() {
122
        initializeDocumentActionsExtensionPoint();
123
        registerDocuments();
124
        registerIcons();
125

    
126
        PropertiesPageManager propertiesManager = ToolsUtilLocator.getPropertiesPageManager();
127
        propertiesManager.registerFactory(new ProjectDocumentsPanelPageFactory());
128

    
129
        File projectFile = getProjectFileFromArguments();
130
        if (projectFile != null) {
131
            // Posponemos la apertura del proyecto ya que en este momento
132
            // puede que no este inicializado algun plugin que precise el
133
            // proyecto para poderse cargar.
134
            PluginsLocator.getManager().addStartupTask(
135
                    "Open project",
136
                    new OpenInitialProjectTask(projectFile), true, 1000);
137
        }
138
    }
139

    
140
    private void registerIcons() {
141
        IconThemeHelper.registerIcon("action", "application-project-new", this);
142
        IconThemeHelper
143
                .registerIcon("action", "application-project-open", this);
144
        IconThemeHelper
145
                .registerIcon("action", "application-project-save", this);
146
        IconThemeHelper.registerIcon("action", "application-project-save-as",
147
                this);
148

    
149
        IconThemeHelper.registerIcon("project", "project-icon", this);
150
    }
151

    
152
    /**
153
     * Returns the file to be opened or null if no parameter or file does not
154
     * exist
155
     *
156
     * @return
157
     */
158
    private File getProjectFileFromArguments() {
159
        String[] theArgs = PluginServices.getArguments();
160
        if (theArgs.length < 3) {
161
            // application-name and extensions-folder are fixed arguments
162
            return null;
163
        }
164
        String lastArg = theArgs[theArgs.length - 1];
165
        if (StringUtils.isEmpty(lastArg)) {
166
            return null;
167
        }
168
        if (lastArg.startsWith("-")) {
169
            // Args starts with "-" are flags
170
            return null;
171
        }
172
        if (!lastArg.toLowerCase().endsWith(Project.FILE_EXTENSION.toLowerCase())) {
173
            LOG.info("Do not open project file, does not have the expected extension '"
174
                    + Project.FILE_EXTENSION + "' (" + lastArg + ").");
175
            return null;
176
        }
177
        File projectFile = new File(lastArg);
178
        if (!projectFile.exists()) {
179
            LOG.info("Do not open project file, '" + projectFile.getAbsolutePath() + "' do not exist.");
180
            return null;
181
        }
182
        return projectFile;
183
    }
184

    
185
    private class OpenInitialProjectTask implements Runnable {
186

    
187
        private File projectFile;
188

    
189
        public OpenInitialProjectTask(File projectFile) {
190
            this.projectFile = projectFile;
191
        }
192

    
193
        @Override
194
        public void run() {
195
            if (this.projectFile == null) {
196
                return;
197
            }
198
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
199
            ActionInfo action = actionManager.getAction("application-project-open");
200
            action.execute(this.projectFile);
201
        }
202
    }
203

    
204
    public ProjectWindow getProjectFrame() {
205
        if (projectFrame == null) {
206
            projectFrame = new ProjectWindow();
207
        }
208
        return projectFrame;
209
    }
210

    
211
    /**
212
     * Muestra la ventana con el gestor de proyectos.
213
     */
214
    public void showProjectWindow() {
215
        if (seedProjectWindow != null) {
216
            if (seedProjectWindow.isClosed()) {
217
                // if it was closed, we just don't open the window now
218
                seedProjectWindow.setClosed(false);
219
                return;
220
            }
221
            WindowInfo winProps = seedProjectWindow;
222
            seedProjectWindow = null;
223
            PluginServices.getMDIManager().addWindow(getProjectFrame());
224
            PluginServices.getMDIManager().changeWindowInfo(getProjectFrame(),
225
                    winProps);
226
        } else {
227
            PluginServices.getMDIManager().addWindow(getProjectFrame());
228
        }
229
    }
230

    
231
    /**
232
     * Muestra la ventana con el gestor de proyectos, con las propiedades de
233
     * ventana especificadas.
234
     */
235
    public void showProjectWindow(WindowInfo wi) {
236
        seedProjectWindow = wi;
237
        showProjectWindow();
238
    }
239

    
240
    /**
241
     * Guarda el proyecto actual en disco.
242
     */
243
    private boolean saveProject() {
244
        boolean saved = false;
245
        // if (p.getPath() == null) {
246
        if (projectPath == null) {
247
            saved = saveAsProject(null);
248
        } else {
249
            long t1, t2;
250
            t1 = System.currentTimeMillis();
251
            saved = writeProject(new File(projectPath), p, false);
252
            t2 = System.currentTimeMillis();
253
            PluginServices.getLogger().info(
254
                    "Project saved. " + (t2 - t1) + " miliseconds");
255
            getProjectFrame().setProject(p);
256
        }
257
        return saved;
258
    }
259

    
260
    private boolean saveAsProject(File file) {
261
        boolean saved = false;
262

    
263
        if (lastSavePath == null) {
264
            lastSavePath = projectPath;
265
        }
266

    
267
        if (file == null) {
268
            Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
269
            JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID,
270
                    prefs.get("ProjectsFolder", null));
271

    
272
            jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
273

    
274
            GenericFileFilter projExtensionFilter = new GenericFileFilter(
275
                    Project.FILE_EXTENSION, MessageFormat.format(PluginServices
276
                            .getText(this, "tipo_fichero_proyecto"),
277
                            Project.FILE_EXTENSION));
278
            jfc.addChoosableFileFilter(projExtensionFilter);
279
            jfc.setFileFilter(projExtensionFilter);
280

    
281
            if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
282
                return saved;
283
            }
284
            file = jfc.getSelectedFile();
285
        }
286

    
287
        if (!(file.getPath().toLowerCase().endsWith(Project.FILE_EXTENSION
288
                .toLowerCase()))) {
289
            file = new File(file.getPath() + Project.FILE_EXTENSION);
290
        }
291
        saved = writeProject(file, p);
292
        String filePath = file.getAbsolutePath();
293
        lastSavePath = filePath.substring(0,
294
                filePath.lastIndexOf(File.separatorChar));
295

    
296
        getProjectFrame().setProject(p);
297
        return saved;
298
    }
299

    
300
    /**
301
     * Checks whether the project and related unsaved data is modified, and
302
     * allows the user to save it.
303
     *
304
     * @return true if the data has been correctly saved, false otherwise
305
     */
306
    private boolean askSave() {
307
        if (p != null && p.hasChanged()) {
308
            TerminationProcess process = Launcher.getTerminationProcess();
309
            UnsavedDataPanel panel = process.getUnsavedDataPanel();
310
            panel.setHeaderText(PluginServices.getText(this,
311
                    "_Select_resources_to_save_before_closing_current_project"));
312
            panel.setAcceptText(
313
                    PluginServices.getText(this, "save_resources"),
314
                    PluginServices
315
                            .getText(this,
316
                                    "Save_the_selected_resources_and_close_current_project"));
317
            panel.setCancelText(PluginServices.getText(this, "Cancel"),
318
                    PluginServices.getText(this, "Return_to_current_project"));
319
            int closeCurrProj;
320
            try {
321
                closeCurrProj = process.manageUnsavedData();
322
                if (closeCurrProj == JOptionPane.NO_OPTION) {
323
                    // the user chose to return to current project
324
                    return false;
325
                }
326
            } catch (Exception e) {
327
                LOG.error("Some data can not be saved", e);
328
            }
329
        }
330
        return true;
331
    }
332

    
333
    @Override
334
    public void execute(String command) {
335
        this.execute(command, null);
336
    }
337

    
338
    @Override
339
    public void execute(String actionCommand, Object[] args) {
340
        if (actionCommand.equals("application-project-new")) {
341
            if (!askSave()) {
342
                return;
343
            }
344

    
345
            projectPath = null;
346
            PluginServices.getMDIManager().closeAllWindows();
347
            setProject(ProjectManager.getInstance().createProject());
348

    
349
            showProjectWindow();
350
            PluginServices.getMainFrame().setTitle(PluginServices.getText(this, "sin_titulo"));
351

    
352
        } else if (actionCommand.equals("application-project-open")) {
353
            if (!askSave()) {
354
                return;
355
            }
356

    
357
            setProject(ProjectManager.getInstance().createProject());
358

    
359
            File projectFile = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
360
            if (projectFile != null && !projectFile.exists()) {
361
                LOG.warn("Can't load project '" + projectFile.getAbsolutePath() + "', file not exist.");
362
                projectFile = null;
363
            }
364

    
365
            if (projectFile == null) {
366
                Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
367
                JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID, prefs.get("ProjectsFolder", null));
368
                ProjectPreviewPanel preview = new ProjectPreviewPanel();
369
                jfc.setAccessory(preview);
370
                jfc.addPropertyChangeListener(preview);
371

    
372
                GenericFileFilter projExtensionFilter
373
                        = new GenericFileFilter(Project.FILE_EXTENSION, PluginServices.getText(this, "tipo_fichero_proyecto"));
374
                jfc.addChoosableFileFilter(projExtensionFilter);
375
                GenericFileFilter bakExtensionFilter
376
                        = new GenericFileFilter(Project.FILE_BAK, PluginServices.getText(this, "tipo_fichero_proyecto_bak"));
377
                jfc.addChoosableFileFilter(bakExtensionFilter);
378
                jfc.setFileFilter(projExtensionFilter);
379

    
380
                if (jfc.showOpenDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
381
                    return;
382
                }
383
                // ProjectDocument.initializeNUMS();
384

    
385
                projectFile = jfc.getSelectedFile();
386
            }
387

    
388
            PluginServices.getMDIManager().closeAllWindows();
389

    
390
            Project o = readProject(projectFile);
391
            if ("bak".equals(FilenameUtils.getExtension(projectFile.getAbsolutePath()))) {
392
                setPath(null);
393
            } else {
394
                setPath(projectFile.getAbsolutePath());
395
            }
396
            // lastPath = getPath();
397
            if (o != null) {
398
                setProject(o);
399
            }
400

    
401
            getProjectFrame().setProject(p);
402
            PluginServices.getMainFrame().setTitle(projectFile.getName());
403
//            getProjectFrame().refreshControls();
404

    
405
            // p.restoreWindowProperties();
406
        } else if (actionCommand.equals("application-project-save")) {
407
            // saveProject();
408
            try {
409
                Launcher.manageUnsavedData("there_are_unsaved_resources");
410
            } catch (Exception e) {
411
                LOG.warn("Can't manage unsaved data", e);
412
            }
413
        } else if (actionCommand.equals("application-project-save-as")) {
414
            File file = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
415
            saveAsProject(file);
416
        }
417

    
418
    }
419

    
420
    private void createEmptyProject() {
421
        setProject(ProjectManager.getInstance().createProject());
422
        p.setName(PluginServices.getText(this, "untitled"));
423
        p.setModified(false);
424
        PluginServices.getMainFrame().setTitle(
425
                PluginServices.getText(this, "sin_titulo"));
426
        setProject(p);
427
        showProjectWindow();
428
    }
429

    
430
    @Override
431
    public void postInitialize() {
432
        PluginsManager pluginsManager = PluginsLocator.getManager();
433
        pluginsManager.addStartupTask(
434
                "createEmptyProject",
435
                new Runnable() {
436
            @Override
437
            public void run() {
438
                createEmptyProject();
439
            }
440
        },
441
                true,
442
                1000
443
        );
444
    }
445

    
446
    /**
447
     * Escribe el proyecto en XML.
448
     *
449
     * @param file Fichero.
450
     * @param p Proyecto.
451
     */
452
    public boolean writeProject(File file, Project p) {
453
        return writeProject(file, p, true);
454
    }
455

    
456
    /**
457
     * Escribe el proyecto en disco. Pero permite decidir si se pide
458
     * confirmaci?n para sobreescribir
459
     *
460
     * @param file Fichero.
461
     * @param p Proyecto.
462
     * @param askConfirmation boolean
463
     * @return
464
     */
465
    public boolean writeProject(File file, Project p, boolean askConfirmation) {
466
        I18nManager i18n = ToolsLocator.getI18nManager();
467
        ApplicationManager application = ApplicationLocator.getManager();
468
        if (askConfirmation && file.exists()) {
469
            int resp = application.confirmDialog(
470
                    i18n.getTranslation("fichero_ya_existe_seguro_desea_guardarlo"),
471
                    i18n.getTranslation("guardar"),
472
                    JOptionPane.YES_NO_OPTION,
473
                    JOptionPane.QUESTION_MESSAGE,
474
                    "Overwrite_project_file"
475
            );
476
            if (resp != JOptionPane.YES_OPTION) {
477
                return false;
478
            }
479
        }
480
        LOG.info("Writing project '" + file.getAbsolutePath() + "'.");
481
        try {
482
            fireBeforeSavingFileEvent(new SaveEvent(this, SaveEvent.BEFORE_SAVING, file));
483
            BufferedImage img = ApplicationLocator.getManager().getUIManager().getImagePreview();
484
            img = scale(img, 0.40);
485
            p.saveState(file, img);
486

    
487
            PluginServices.getMainFrame().setTitle(file.getName());
488
            setPath(file.toString());
489

    
490
        } catch (Exception e) {
491
            application.messageDialog(
492
                    i18n.getTranslation("_Problems_saving_the_project_XnlX_It_is_possible_that_this_was_not_saved_properly_and_can_not_be_loaded_again"),
493
                    null,
494
                    i18n.getTranslation("guardar"),
495
                    JOptionPane.ERROR_MESSAGE,
496
                    "Problems_saving_the_project"
497
            );
498
            LOG.warn("Error writing project '" + file.getAbsolutePath() + "'.", e);
499
            return false;
500
        }
501
        LOG.warn("Wrote project '" + file.getAbsolutePath() + "'.");
502
        return true;
503
    }
504

    
505
    boolean isValidZIP(final File file) {
506
        ZipFile zipfile = null;
507
        try {
508
            zipfile = new ZipFile(file);
509
            return true;
510
        } catch (IOException e) {
511
            return false;
512
        } finally {
513
            try {
514
                if (zipfile != null) {
515
                    zipfile.close();
516
                    zipfile = null;
517
                }
518
            } catch (IOException e) {
519
            }
520
        }
521
    }
522

    
523
    private BufferedImage scale(BufferedImage before, double factor) {
524
        int w = (int) (before.getWidth() * factor);
525
        int h = (int) (before.getHeight() * factor);
526
        BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
527
        AffineTransform at = new AffineTransform();
528
        at.scale(factor, factor);
529
        AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
530
        after = scaleOp.filter(before, after);
531
        return after;
532
    }
533

    
534
    public Project readProject(String path) {
535
        Project project = ProjectManager.getInstance().createProject();
536

    
537
        project.loadState(new File(path));
538
        return (Project) project;
539
    }
540

    
541
    /**
542
     * Lee del XML el proyecto.<br>
543
     * <br>
544
     *
545
     * Reads the XML of the project.<br>
546
     * It returns a project object holding all needed info that is not linked to
547
     * the Project Dialog. <br>
548
     * In case you want the project to be linked to the window you must set this
549
     * object to the extension:<br>
550
     *
551
     * <b>Example:</b><br>
552
     *
553
     * ...<br>
554
     * .
555
     * ..<br>
556
     * Project p = ProjectExtension.readProject(projectFile);<br>
557
     * ProjectExtension.setProject(p); ...<br>
558
     * .
559
     * ..<br>
560
     *
561
     * @param file Fichero.
562
     *
563
     * @return Project
564
     *
565
     */
566
    public Project readProject(File file) {
567
        Project project = ProjectManager.getInstance().createProject();
568

    
569
        project.loadState(file);
570
        Set<String> unloadedObjects = project.getUnloadedObjects();
571
        List<Exception> errors = project.getLoadErrors();
572

    
573
        if (!CollectionUtils.isEmpty(unloadedObjects)) {
574
            StringBuilder builder = new StringBuilder();
575
            builder.append("Unloaded elements loading the project:\n");
576
            Iterator<String> it = unloadedObjects.iterator();
577
            while (it.hasNext()) {
578
                builder.append("\t");
579
                builder.append(it.next());
580
                builder.append("\n");
581
            }
582

    
583
            LOG.warn(builder.toString());
584
        }
585
        if (!CollectionUtils.isEmpty(unloadedObjects) || !CollectionUtils.isEmpty(errors)) {
586
            ApplicationManager application = ApplicationLocator.getManager();
587
            I18nManager i18nManager = ToolsLocator.getI18nManager();
588

    
589
            application.messageDialog(
590
                    i18nManager.getTranslation("_some_project_elements_could_not_be_loaded") + "\n"
591
                    + i18nManager.getTranslation("_maybe_you_need_to_install_any_plugins") + "\n"
592
                    + i18nManager.getTranslation("_Recovered_data_may_be_corrupted") + "\n\n"
593
                    + i18nManager.getTranslation("_see_error_log_for_more_information"),
594
                    i18nManager.getTranslation("warning"),
595
                    JOptionPane.WARNING_MESSAGE);
596

    
597
        } else {
598

    
599
        }
600
        return (Project) project;
601
    }
602

    
603
    /**
604
     * Devuelve el proyecto.
605
     *
606
     * @return Proyecto.
607
     */
608
    public Project getProject() {
609
        return p;
610
    }
611

    
612
    /**
613
     * @see org.gvsig.andami.plugins.IExtension#isEnabled()
614
     */
615
    public boolean isEnabled() {
616
        return true;
617
    }
618

    
619
    /**
620
     * @see org.gvsig.andami.plugins.IExtension#isVisible()
621
     */
622
    public boolean isVisible() {
623
        return true;
624
    }
625

    
626
    /**
627
     * Sets the project
628
     *
629
     * @param p
630
     */
631
    public void setProject(Project p) {
632
        this.p = p;
633
        getProjectFrame().setProject(p);
634
    }
635

    
636
    private void registerDocuments() {
637
        ViewManager.register();
638
    }
639

    
640
    private void initializeDocumentActionsExtensionPoint() {
641
        ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
642
        epMan.add(
643
                "DocumentActions_View",
644
                "Context menu options of the view document list"
645
                + " in the project window "
646
                + "(register instances of "
647
                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
648
    }
649

    
650
    public static String getPath() {
651
        return projectPath;
652
    }
653

    
654
    public static void setPath(String path) {
655
        projectPath = path;
656
    }
657

    
658
    public IWindow getProjectWindow() {
659
        return getProjectFrame();
660
    }
661

    
662
    @Override
663
    public IExtensionStatus getStatus() {
664
        return this;
665
    }
666

    
667
    @Override
668
    public boolean hasUnsavedData() {
669
        return p.hasChanged();
670
    }
671

    
672
    @Override
673
    public IUnsavedData[] getUnsavedData() {
674
        if (hasUnsavedData()) {
675
            UnsavedProject data = new UnsavedProject(this);
676
            IUnsavedData[] dataArray = {data};
677
            return dataArray;
678
        } else {
679
            return null;
680
        }
681
    }
682

    
683
    /**
684
     * Implements the IUnsavedData interface to show unsaved projects in the
685
     * Unsavad Data dialog.
686
     *
687
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
688
     */
689
    public class UnsavedProject extends UnsavedData {
690

    
691
        public UnsavedProject(IExtension extension) {
692
            super(extension);
693
        }
694

    
695
        @Override
696
        public String getDescription() {
697
            if (getPath() == null) {
698
                return PluginServices.getText(ProjectExtension.this,
699
                        "Unnamed_new_gvsig_project_");
700
            } else {
701
                return PluginServices.getText(ProjectExtension.this,
702
                        "Modified_project_");
703
            }
704
        }
705

    
706
        @Override
707
        public String getResourceName() {
708
            if (getPath() == null) {
709
                return PluginServices.getText(ProjectExtension.this, "Unnamed");
710
            } else {
711
                return getPath();
712
            }
713

    
714
        }
715

    
716
        @Override
717
        public boolean saveData() {
718
            return saveProject();
719
        }
720

    
721
        @Override
722
        public String getIcon() {
723
            return "project-icon";
724
        }
725
    }
726

    
727
    @Override
728
    public IMonitorableTask[] getRunningProcesses() {
729
        // TODO Auto-generated method stub
730
        return null;
731
    }
732

    
733
    @Override
734
    public boolean hasRunningProcesses() {
735
        // TODO Auto-generated method stub
736
        return false;
737
    }
738

    
739
    /**
740
     * Adds the specified before saving listener to receive "before saving file
741
     * events" from this component. If l is null, no exception is thrown and no
742
     * action is performed.
743
     *
744
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
745
     *
746
     * @param l the before saving listener.
747
     * @see SaveEvent
748
     * @see BeforeSavingListener
749
     * @see #removeListener(BeforeSavingListener)
750
     * @see #getBeforeSavingListeners
751
     */
752
    public synchronized void addListener(BeforeSavingListener l) {
753
        if (l == null) {
754
            return;
755
        }
756
        if (!this.beforeSavingListeners.contains(l)) {
757
            this.beforeSavingListeners.add(l);
758
        }
759
    }
760

    
761
    /**
762
     * Adds the specified after saving listener to receive "after saving file
763
     * events" from this component. If l is null, no exception is thrown and no
764
     * action is performed.
765
     *
766
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
767
     *
768
     * @param l the after saving listener.
769
     * @see SaveEvent
770
     * @see AfterSavingListener
771
     * @see #removeListener(AfterSavingListener)
772
     * @see #getAfterSavingListeners()
773
     */
774
    public synchronized void addListener(AfterSavingListener l) {
775
        if (l == null) {
776
            return;
777
        }
778

    
779
        if (!this.afterSavingListeners.contains(l)) {
780
            this.afterSavingListeners.add(l);
781
        }
782

    
783
    }
784

    
785
    /**
786
     * Returns an array of all the before saving listeners registered on this
787
     * component.
788
     *
789
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
790
     *
791
     * @return all of this component's <code>BeforeSavingListener</code>s or an
792
     * empty array if no key listeners are currently registered
793
     *
794
     * @see #addBeforeSavingListener(BeforeSavingListener)
795
     * @see #removeBeforeSavingListener(BeforeSavingListener)
796
     */
797
    public synchronized BeforeSavingListener[] getBeforeSavingListeners() {
798
        return this.beforeSavingListeners
799
                .toArray(new BeforeSavingListener[]{});
800
    }
801

    
802
    /**
803
     * Returns an array of all the after saving listeners registered on this
804
     * component.
805
     *
806
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
807
     *
808
     * @return all of this component's <code>AfterSavingListener</code>s or an
809
     * empty array if no key listeners are currently registered
810
     *
811
     * @see #addAfterSavingListener(AfterSavingListener)
812
     * @see #removeAfterSavingListener
813
     */
814
    public synchronized AfterSavingListener[] getAfterSavingListeners() {
815
        return this.afterSavingListeners.toArray(new AfterSavingListener[]{});
816

    
817
    }
818

    
819
    /**
820
     * Removes the specified before saving listener so that it no longer
821
     * receives save file events from this component. This method performs no
822
     * function, nor does it throw an exception, if the listener specified by
823
     * the argument was not previously added to this component. If listener
824
     * <code>l</code> is <code>null</code>, no exception is thrown and no action
825
     * is performed.
826
     *
827
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
828
     *
829
     * @param l the before saving listener
830
     * @see SaveEvent
831
     * @see BeforeSavingListener
832
     * @see #addListener(BeforeSavingListener)
833
     * @see #getBeforeSavingListeners()
834
     */
835
    public synchronized void removeListener(BeforeSavingListener l) {
836
        if (l == null) {
837
            return;
838
        }
839

    
840
        this.beforeSavingListeners.remove(l);
841
    }
842

    
843
    /**
844
     * Removes the specified after saving listener so that it no longer receives
845
     * save file events from this component. This method performs no function,
846
     * nor does it throw an exception, if the listener specified by the argument
847
     * was not previously added to this component. If listener <code>l</code> is
848
     * <code>null</code>, no exception is thrown and no action is performed.
849
     *
850
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
851
     *
852
     * @param l the after saving listener
853
     * @see SaveEvent
854
     * @see AfterSavingListener
855
     * @see #addListener(AfterSavingListener)
856
     * @see #getAfterSavingListeners()
857
     */
858
    public synchronized void removeListener(AfterSavingListener l) {
859
        if (l == null) {
860
            return;
861
        }
862

    
863
        this.afterSavingListeners.remove(l);
864
    }
865

    
866
    /**
867
     * Reports a before saving file event.
868
     *
869
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
870
     *
871
     * @param evt the before saving file event
872
     */
873
    protected void fireBeforeSavingFileEvent(SaveEvent evt) {
874
        if ((evt.getID() != SaveEvent.BEFORE_SAVING) || (evt.getFile() == null)) {
875
            return;
876
        }
877

    
878
        Iterator<BeforeSavingListener> iter = this.beforeSavingListeners
879
                .iterator();
880

    
881
        while (iter.hasNext()) {
882
            iter.next().beforeSaving(evt);
883
        }
884
    }
885

    
886
    /**
887
     * Reports a after saving file event.
888
     *
889
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
890
     *
891
     * @param evt the after saving file event
892
     */
893
    protected void fireAfterSavingFileEvent(SaveEvent evt) {
894
        if ((evt.getID() != SaveEvent.AFTER_SAVING) || (evt.getFile() == null)) {
895
            return;
896
        }
897
        Iterator<AfterSavingListener> iter = this.afterSavingListeners
898
                .iterator();
899

    
900
        while (iter.hasNext()) {
901
            iter.next().afterSaving(evt);
902
        }
903

    
904
    }
905
}