Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / extension / ProjectExtension.java @ 43828

History | View | Annotate | Download (28.5 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.FileOutputStream;
32
import java.io.IOException;
33
import java.text.MessageFormat;
34
import java.util.ArrayList;
35
import java.util.Iterator;
36
import java.util.List;
37
import java.util.Set;
38
import java.util.prefs.Preferences;
39
import java.util.zip.ZipEntry;
40
import java.util.zip.ZipException;
41
import java.util.zip.ZipFile;
42
import java.util.zip.ZipOutputStream;
43
import javax.imageio.ImageIO;
44

    
45
import javax.swing.JOptionPane;
46
import javax.swing.SwingUtilities;
47
import org.apache.commons.collections.CollectionUtils;
48
import org.apache.commons.io.IOUtils;
49

    
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

    
53
import org.gvsig.tools.util.ArrayUtils;
54

    
55
import org.apache.commons.lang.StringUtils;
56

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

    
92

    
93
/**
94
 * Extension que proporciona controles para crear proyectos nuevos, abrirlos y
95
 * guardarlos. Adem?s los tipos de tabla que soporta el proyecto son a?adidos en
96
 * esta clase.
97
 *
98
 */
99
public class ProjectExtension extends Extension implements IExtensionStatus {
100
        private static final Logger LOG = LoggerFactory
101
                        .getLogger(ProjectExtension.class);
102

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

    
120
        private List<BeforeSavingListener> beforeSavingListeners = new ArrayList<BeforeSavingListener>();
121

    
122
        private List<AfterSavingListener> afterSavingListeners = new ArrayList<AfterSavingListener>();
123

    
124
        public void initialize() {
125
            initializeDocumentActionsExtensionPoint();
126
            registerDocuments();
127
            registerIcons();
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
154
         * or file does not 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
            private File projectFile;
187
            public OpenInitialProjectTask(File projectFile) {
188
                this.projectFile = projectFile;
189
            }
190
            public void run() {
191
                if (this.projectFile == null) {
192
                    return;
193
                }
194
                ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
195
                ActionInfo action = actionManager.getAction("application-project-open");
196
                action.execute(this.projectFile);
197
            }
198
        }
199

    
200
        public ProjectWindow getProjectFrame() {
201
                if (projectFrame == null) {
202
                        projectFrame = new ProjectWindow();
203
                }
204
                return projectFrame;
205
        }
206

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

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

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

    
256
        private boolean saveAsProject(File file) {
257
                boolean saved = false;
258

    
259
                if (lastSavePath == null) {
260
                        lastSavePath = projectPath;
261
                }
262

    
263
                if (file == null) {
264
                        Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
265
                        JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID,
266
                                        prefs.get("ProjectsFolder", null));
267

    
268
                        jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
269

    
270
                        GenericFileFilter projExtensionFilter = new GenericFileFilter(
271
                                        Project.FILE_EXTENSION, MessageFormat.format(PluginServices
272
                                                        .getText(this, "tipo_fichero_proyecto"),
273
                                                        Project.FILE_EXTENSION));
274
      jfc.addChoosableFileFilter(projExtensionFilter);
275
      jfc.setFileFilter(projExtensionFilter);
276

    
277
                        if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
278
                                return saved;
279
                        }
280
                        file = jfc.getSelectedFile();
281
                }
282

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

    
292
                getProjectFrame().refreshControls();
293
                return saved;
294
        }
295

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

    
329
        public void execute(String command) {
330
                this.execute(command, null);
331
        }
332

    
333
    public void execute(String actionCommand, Object[] args) {
334
        if (actionCommand.equals("application-project-new")) {
335
            if (!askSave()) {
336
                return;
337
            }
338

    
339
            projectPath = null;
340
            PluginServices.getMDIManager().closeAllWindows();
341
            setProject(ProjectManager.getInstance().createProject());
342

    
343
            showProjectWindow();
344
            PluginServices.getMainFrame().setTitle(PluginServices.getText(this, "sin_titulo"));
345

    
346
        } else if (actionCommand.equals("application-project-open")) {
347
            if (!askSave()) {
348
                return;
349
            }
350

    
351
            setProject(ProjectManager.getInstance().createProject());
352

    
353
            File projectFile = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
354
            if (projectFile != null && !projectFile.exists()) {
355
                LOG.warn("Can't load project '" + projectFile.getAbsolutePath() + "', file not exist.");
356
                projectFile = null;
357
            }
358

    
359
            if (projectFile == null) {
360
                Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
361
                JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID, prefs.get("ProjectsFolder", null));
362
                ProjectPreviewPanel preview = new ProjectPreviewPanel();
363
                jfc.setAccessory(preview);
364
                jfc.addPropertyChangeListener(preview);                
365

    
366
                GenericFileFilter projExtensionFilter =
367
                    new GenericFileFilter(Project.FILE_EXTENSION, PluginServices.getText(this, "tipo_fichero_proyecto"));
368
                jfc.addChoosableFileFilter(projExtensionFilter);
369
                jfc.setFileFilter(projExtensionFilter);
370

    
371
                if (jfc.showOpenDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
372
                    return;
373
                }
374
                // ProjectDocument.initializeNUMS();
375

    
376
                projectFile = jfc.getSelectedFile();
377
            }
378

    
379
            PluginServices.getMDIManager().closeAllWindows();
380

    
381
            Project o = readProject(projectFile);
382
            setPath(projectFile.getAbsolutePath());
383
            // lastPath = getPath();
384
            if (o != null) {
385
                setProject(o);
386
            }
387

    
388
            getProjectFrame().setProject(p);
389
            PluginServices.getMainFrame().setTitle(projectFile.getName());
390
            getProjectFrame().refreshControls();
391

    
392
            // p.restoreWindowProperties();
393

    
394
        } else if (actionCommand.equals("application-project-save")) {
395
            // saveProject();
396
            try {
397
                Launcher.manageUnsavedData("there_are_unsaved_resources");
398
            } catch (Exception e) {
399
                LOG.warn("Can't manage unsaved data", e);
400
            }
401
        } else if (actionCommand.equals("application-project-save-as")) {
402
            File file = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
403
            saveAsProject(file);
404
        }
405

    
406
    }
407

    
408

    
409
    private void createEmptyProject() {
410
        setProject(ProjectManager.getInstance().createProject());
411
        p.setName(PluginServices.getText(this, "untitled"));
412
        p.setModified(false);
413
        PluginServices.getMainFrame().setTitle(
414
                PluginServices.getText(this, "sin_titulo"));
415
        setProject(p);
416
        showProjectWindow();
417
    }
418

    
419
    /**
420
     * @see com.iver.mdiApp.plugins.IExtension#postInitialize()
421
     */
422
    public void postInitialize() {
423
        try {
424
            if( !SwingUtilities.isEventDispatchThread() ) {
425
                SwingUtilities.invokeAndWait(new Runnable() {
426
                    public void run() {
427
                        createEmptyProject();
428
                    }
429
                });
430
            } else {
431
                createEmptyProject();
432
            }
433
        } catch (Exception e) {
434
            LOG.warn("Can't load initial project.",e);
435
        }
436
    }
437

    
438

    
439
        /**
440
         * Escribe el proyecto en XML.
441
         *
442
         * @param file
443
         *            Fichero.
444
         * @param p
445
         *            Proyecto.
446
         */
447
        public boolean writeProject(File file, Project p) {
448
                return writeProject(file, p, true);
449
        }
450

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

    
481
            fout = new FileOutputStream(file);
482
            zout = new ZipOutputStream(fout);
483
            p.saveState(zout, file.getParentFile());
484

    
485
            zout.putNextEntry(new ZipEntry("preview.jpg"));
486
            BufferedImage img = ApplicationLocator.getManager().getUIManager().getImagePreview();
487
            img = scale(img, 0.40);
488
            try {
489
                ImageIO.write(img, "jpg", zout);
490
            } catch (IOException ex) {
491
                LOG.warn("Can't save preview image'.", ex);
492
            }
493
            fireAfterSavingFileEvent(new SaveEvent(this, SaveEvent.AFTER_SAVING, file));
494
            IOUtils.closeQuietly(zout);
495
            IOUtils.closeQuietly(fout);
496

    
497
            if( !isValidZIP(file) ) {
498
                throw new ZipException("Invalid project file '"+file.getAbsolutePath()+"'");
499
            }
500
            
501
            PluginServices.getMainFrame().setTitle(file.getName());
502
            setPath(file.toString());
503

    
504
        } catch (Exception e) {
505
            application.messageDialog(
506
                    i18n.getTranslation("_Problems_saving_the_project_XnlX_It_is_possible_that_this_was_not_saved_properly_and_can_not_be_loaded_again"), 
507
                    null, 
508
                    i18n.getTranslation("guardar"), 
509
                    JOptionPane.ERROR_MESSAGE, 
510
                    "Problems_saving_the_project"
511
            );
512
            LOG.warn("Error writing project '"+file.getAbsolutePath()+"'.", e);
513
            return false;
514
        } finally {
515
            IOUtils.closeQuietly(zout);
516
            IOUtils.closeQuietly(fout);
517
        }
518
        
519
        LOG.warn("Wrote project '"+file.getAbsolutePath()+"'.");
520
        return true;
521
    }
522

    
523
    boolean isValidZIP(final File file) {
524
        ZipFile zipfile = null;
525
        try {
526
            zipfile = new ZipFile(file);
527
            return true;
528
        } catch (IOException e) {
529
            return false;
530
        } finally {
531
            try {
532
                if (zipfile != null) {
533
                    zipfile.close();
534
                    zipfile = null;
535
                }
536
            } catch (IOException e) {
537
            }
538
        }
539
    }
540

    
541
    private BufferedImage scale(BufferedImage before, double factor) {
542
        int w = (int) (before.getWidth()*factor);
543
        int h = (int) (before.getHeight()*factor);
544
        BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
545
        AffineTransform at = new AffineTransform();
546
        at.scale(factor, factor);
547
        AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
548
        after = scaleOp.filter(before, after);        
549
        return after;
550
    }
551
    
552
        public Project readProject(String path) {
553
                Project project = ProjectManager.getInstance().createProject();
554

    
555
                project.loadState(new File(path));
556
                return (Project) project;
557
        }
558

    
559
        /**
560
         * Lee del XML el proyecto.<br>
561
         * <br>
562
         *
563
         * Reads the XML of the project.<br>
564
         * It returns a project object holding all needed info that is not linked to
565
         * the Project Dialog. <br>
566
         * In case you want the project to be linked to the window you must set this
567
         * object to the extension:<br>
568
         *
569
         * <b>Example:</b><br>
570
         *
571
         * ...<br>
572
         * ...<br>
573
         * Project p = ProjectExtension.readProject(projectFile);<br>
574
         * ProjectExtension.setProject(p); ...<br>
575
         * ...<br>
576
         *
577
         * @param file
578
         *            Fichero.
579
         *
580
         * @return Project
581
         *
582
         */
583
        public Project readProject(File file) {
584
                Project project = ProjectManager.getInstance().createProject();
585

    
586
                project.loadState(file);
587
                Set<String> unloadedObjects = project.getUnloadedObjects();
588
        List<Exception> errors = project.getLoadErrors();
589
        
590
                if( !CollectionUtils.isEmpty(unloadedObjects) ) {
591
                    StringBuilder builder = new StringBuilder();
592
                    builder.append("Unloaded elements loading the project:\n");
593
                    Iterator<String> it = unloadedObjects.iterator();
594
                    while(it.hasNext()){
595
                builder.append("\t");
596
                        builder.append(it.next());
597
                        builder.append("\n");
598
                    }
599

    
600
                    LOG.warn(builder.toString());
601
        }
602
                if( !CollectionUtils.isEmpty(unloadedObjects) || !CollectionUtils.isEmpty(errors) ) {
603
                    ApplicationManager application = ApplicationLocator.getManager();
604
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
605

    
606
                    application.messageDialog(
607
                        i18nManager.getTranslation("_some_project_elements_could_not_be_loaded")+"\n"+
608
                        i18nManager.getTranslation("_maybe_you_need_to_install_any_plugins")+"\n"+
609
                        i18nManager.getTranslation("_Recovered_data_may_be_corrupted")+"\n\n"+
610
                        i18nManager.getTranslation("_see_error_log_for_more_information"),
611
                    i18nManager.getTranslation("warning"),
612
                    JOptionPane.WARNING_MESSAGE);
613

    
614
                } else {
615
            
616
        }
617
                return (Project) project;
618
        }
619

    
620
        /**
621
         * Devuelve el proyecto.
622
         *
623
         * @return Proyecto.
624
         */
625
        public Project getProject() {
626
                return p;
627
        }
628

    
629
        /**
630
         * @see org.gvsig.andami.plugins.IExtension#isEnabled()
631
         */
632
        public boolean isEnabled() {
633
                return true;
634
        }
635

    
636
        /**
637
         * @see org.gvsig.andami.plugins.IExtension#isVisible()
638
         */
639
        public boolean isVisible() {
640
                return true;
641
        }
642

    
643
        /**
644
         * Sets the project
645
         *
646
         * @param p
647
         */
648
        public void setProject(Project p) {
649
                this.p = p;
650
                getProjectFrame().setProject(p);
651
        }
652

    
653
        private void registerDocuments() {
654
                ViewManager.register();
655
        }
656

    
657
        private void initializeDocumentActionsExtensionPoint() {
658
                ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
659
                epMan.add(
660
                                "DocumentActions_View",
661
                                "Context menu options of the view document list"
662
                                                + " in the project window "
663
                                                + "(register instances of "
664
                                                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
665
        }
666

    
667
        public static String getPath() {
668
                return projectPath;
669
        }
670

    
671
        public static void setPath(String path) {
672
                projectPath = path;
673
        }
674

    
675
        public IWindow getProjectWindow() {
676
                return getProjectFrame();
677
        }
678

    
679
        public IExtensionStatus getStatus() {
680
                return this;
681
        }
682

    
683
        public boolean hasUnsavedData() {
684
                return p.hasChanged();
685
        }
686

    
687
        public IUnsavedData[] getUnsavedData() {
688
                if (hasUnsavedData()) {
689
                        UnsavedProject data = new UnsavedProject(this);
690
                        IUnsavedData[] dataArray = { data };
691
                        return dataArray;
692
                } else {
693
                        return null;
694
                }
695
        }
696

    
697
        /**
698
         * Implements the IUnsavedData interface to show unsaved projects in the
699
         * Unsavad Data dialog.
700
         *
701
         * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
702
         */
703
        public class UnsavedProject extends UnsavedData {
704

    
705
                public UnsavedProject(IExtension extension) {
706
                        super(extension);
707
                }
708

    
709
                public String getDescription() {
710
                        if (getPath() == null) {
711
                                return PluginServices.getText(ProjectExtension.this,
712
                                                "Unnamed_new_gvsig_project_");
713
                        } else {
714
                                return PluginServices.getText(ProjectExtension.this,
715
                                                "Modified_project_");
716
                        }
717
                }
718

    
719
                public String getResourceName() {
720
                        if (getPath() == null) {
721
                                return PluginServices.getText(ProjectExtension.this, "Unnamed");
722
                        } else {
723
                                return getPath();
724
                        }
725

    
726
                }
727

    
728
                public boolean saveData() {
729
                        return saveProject();
730
                }
731

    
732
                public String getIcon() {
733
                        return "project-icon";
734
                }
735
        }
736

    
737
        public IMonitorableTask[] getRunningProcesses() {
738
                // TODO Auto-generated method stub
739
                return null;
740
        }
741

    
742
        public boolean hasRunningProcesses() {
743
                // TODO Auto-generated method stub
744
                return false;
745
        }
746

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

    
770
        /**
771
         * Adds the specified after saving listener to receive
772
         * "after saving file events" from this component. If l is null, no
773
         * exception is thrown and no action is performed.
774
         *
775
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
776
         *
777
         * @param l
778
         *            the after saving listener.
779
         * @see SaveEvent
780
         * @see AfterSavingListener
781
         * @see #removeListener(AfterSavingListener)
782
         * @see #getAfterSavingListeners()
783
         */
784
        public synchronized void addListener(AfterSavingListener l) {
785
                if (l == null) {
786
                        return;
787
                }
788

    
789
                if (!this.afterSavingListeners.contains(l)) {
790
                        this.afterSavingListeners.add(l);
791
                }
792

    
793
        }
794

    
795
        /**
796
         * Returns an array of all the before saving listeners registered on this
797
         * component.
798
         *
799
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
800
         *
801
         * @return all of this component's <code>BeforeSavingListener</code>s or an
802
         *         empty array if no key listeners are currently registered
803
         *
804
         * @see #addBeforeSavingListener(BeforeSavingListener)
805
         * @see #removeBeforeSavingListener(BeforeSavingListener)
806
         */
807
        public synchronized BeforeSavingListener[] getBeforeSavingListeners() {
808
                return this.beforeSavingListeners
809
                                .toArray(new BeforeSavingListener[] {});
810
        }
811

    
812
        /**
813
         * Returns an array of all the after saving listeners registered on this
814
         * component.
815
         *
816
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
817
         *
818
         * @return all of this component's <code>AfterSavingListener</code>s or an
819
         *         empty array if no key listeners are currently registered
820
         *
821
         * @see #addAfterSavingListener(AfterSavingListener)
822
         * @see #removeAfterSavingListener
823
         */
824
        public synchronized AfterSavingListener[] getAfterSavingListeners() {
825
                return this.afterSavingListeners.toArray(new AfterSavingListener[] {});
826

    
827
        }
828

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

    
851
                this.beforeSavingListeners.remove(l);
852
        }
853

    
854
        /**
855
         * Removes the specified after saving listener so that it no longer receives
856
         * save file events from this component. This method performs no function,
857
         * nor does it throw an exception, if the listener specified by the argument
858
         * was not previously added to this component. If listener <code>l</code> is
859
         * <code>null</code>, no exception is thrown and no action is performed.
860
         *
861
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
862
         *
863
         * @param l
864
         *            the after saving listener
865
         * @see SaveEvent
866
         * @see AfterSavingListener
867
         * @see #addListener(AfterSavingListener)
868
         * @see #getAfterSavingListeners()
869
         */
870
        public synchronized void removeListener(AfterSavingListener l) {
871
                if (l == null) {
872
                        return;
873
                }
874

    
875
                this.afterSavingListeners.remove(l);
876
        }
877

    
878
        /**
879
         * Reports a before saving file event.
880
         *
881
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
882
         *
883
         * @param evt
884
         *            the before saving file event
885
         */
886
        protected void fireBeforeSavingFileEvent(SaveEvent evt) {
887
                if ((evt.getID() != SaveEvent.BEFORE_SAVING) || (evt.getFile() == null)) {
888
                        return;
889
                }
890

    
891
                Iterator<BeforeSavingListener> iter = this.beforeSavingListeners
892
                                .iterator();
893

    
894
                while (iter.hasNext()) {
895
                        iter.next().beforeSaving(evt);
896
                }
897
        }
898

    
899
        /**
900
         * Reports a after saving file event.
901
         *
902
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
903
         *
904
         * @param evt
905
         *            the after saving file event
906
         */
907
        protected void fireAfterSavingFileEvent(SaveEvent evt) {
908
                if ((evt.getID() != SaveEvent.AFTER_SAVING) || (evt.getFile() == null)) {
909
                        return;
910
                }
911
                Iterator<AfterSavingListener> iter = this.afterSavingListeners
912
                                .iterator();
913

    
914
                while (iter.hasNext()) {
915
                        iter.next().afterSaving(evt);
916
                }
917

    
918
        }
919
}