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

History | View | Annotate | Download (31.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.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.filedialogchooser.FileDialogChooser;
76
import org.gvsig.filedialogchooser.FileDialogChooserManager;
77
import org.gvsig.gui.beans.swing.JFileChooser;
78
import org.gvsig.propertypage.PropertiesPageManager;
79
import org.gvsig.tools.ToolsLocator;
80
import org.gvsig.tools.dataTypes.DataTypes;
81
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
82
import org.gvsig.tools.folders.FoldersManager;
83
import org.gvsig.tools.i18n.I18nManager;
84
import org.gvsig.tools.locator.LocatorException;
85
import org.gvsig.tools.util.ToolsUtilLocator;
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
 * Extension que proporciona controles para crear proyectos nuevos, abrirlos y
94
 * guardarlos. Adem?s los tipos de tabla que soporta el proyecto son a?adidos en
95
 * esta clase.
96
 *
97
 */
98
public class ProjectExtension extends Extension implements IExtensionStatus {
99

    
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 final List<BeforeSavingListener> beforeSavingListeners;
121

    
122
    private final List<AfterSavingListener> afterSavingListeners;
123

    
124
    public ProjectExtension() {
125
        this.afterSavingListeners = new ArrayList<>();
126
        this.beforeSavingListeners = new ArrayList<>();
127
    }
128

    
129
    @Override
130
    public void initialize() {
131
        initializeDocumentActionsExtensionPoint();
132
        registerDocuments();
133
        registerIcons();
134

    
135
        PropertiesPageManager propertiesManager = ToolsUtilLocator.getPropertiesPageManager();
136
        propertiesManager.registerFactory(new ProjectDocumentsPanelPageFactory());
137

    
138
        File projectFile = getProjectFileFromArguments();
139
        if (projectFile != null) {
140
            // Posponemos la apertura del proyecto ya que en este momento
141
            // puede que no este inicializado algun plugin que precise el
142
            // proyecto para poderse cargar.
143
            PluginsLocator.getManager().addStartupTask(
144
                    "Open project",
145
                    new OpenInitialProjectTask(projectFile), true, 1000);
146
        }
147
    }
148

    
149
    private void registerIcons() {
150
        IconThemeHelper.registerIcon("action", "application-project-new", this);
151
        IconThemeHelper
152
                .registerIcon("action", "application-project-open", this);
153
        IconThemeHelper
154
                .registerIcon("action", "application-project-save", this);
155
        IconThemeHelper.registerIcon("action", "application-project-save-as",
156
                this);
157

    
158
        IconThemeHelper.registerIcon("project", "project-icon", this);
159
        IconThemeHelper.registerIcon("project", "temporary-table-icon", this);
160
    }
161

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

    
195
    private class OpenInitialProjectTask implements Runnable {
196

    
197
        private final File projectFile;
198

    
199
        public OpenInitialProjectTask(File projectFile) {
200
            this.projectFile = projectFile;
201
        }
202

    
203
        @Override
204
        public void run() {
205
            if (this.projectFile == null) {
206
                return;
207
            }
208
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
209
            ActionInfo action = actionManager.getAction("application-project-open");
210
            action.execute(this.projectFile);
211
        }
212
    }
213

    
214
    public ProjectWindow getProjectFrame() {
215
        if (projectFrame == null) {
216
            projectFrame = new ProjectWindow();
217
        }
218
        return projectFrame;
219
    }
220

    
221
    /**
222
     * Muestra la ventana con el gestor de proyectos.
223
     */
224
    public void showProjectWindow() {
225
        if (seedProjectWindow != null) {
226
            if (seedProjectWindow.isClosed()) {
227
                // if it was closed, we just don't open the window now
228
                seedProjectWindow.setClosed(false);
229
                return;
230
            }
231
            WindowInfo winProps = seedProjectWindow;
232
            seedProjectWindow = null;
233
            PluginServices.getMDIManager().addWindow(getProjectFrame());
234
            PluginServices.getMDIManager().changeWindowInfo(getProjectFrame(),
235
                    winProps);
236
        } else {
237
            PluginServices.getMDIManager().addWindow(getProjectFrame());
238
        }
239
    }
240

    
241
    /**
242
     * Muestra la ventana con el gestor de proyectos, con las propiedades de
243
     * ventana especificadas.
244
     * @param wi
245
     */
246
    public void showProjectWindow(WindowInfo wi) {
247
        seedProjectWindow = wi;
248
        showProjectWindow();
249
    }
250

    
251
    /**
252
     * Guarda el proyecto actual en disco.
253
     */
254
    private boolean saveProject() {
255
        boolean saved;
256
        if (projectPath == null) {
257
            saved = saveAsProject(null);
258
        } else {
259
            long t1, t2;
260
            t1 = System.currentTimeMillis();
261
            saved = writeProject(new File(projectPath), p, false);
262
            t2 = System.currentTimeMillis();
263
            PluginServices.getLogger().info(
264
                    "Project saved. " + (t2 - t1) + " miliseconds");
265
            getProjectFrame().setProject(p);
266
        }
267
        return saved;
268
    }
269

    
270
    private boolean saveAsProject(File file) {
271
        boolean saved = false;
272

    
273
        if (lastSavePath == null) {
274
            lastSavePath = projectPath;
275
        }
276

    
277
        if (file == null) {
278
            FileDialogChooserManager fileDialogChooserManager = ToolsUtilLocator.getFileDialogChooserManager();
279
            FileDialogChooser jfc = fileDialogChooserManager.create(PROJECT_FILE_CHOOSER_ID);
280
            if (lastSavePath == null) {
281
                jfc.setCurrentDirectory(getPreferredProjectsFolder());
282
            } else {
283
                jfc.setCurrentDirectory(new File(lastSavePath));
284
            }
285
            jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
286

    
287
            GenericFileFilter projExtensionFilter = new GenericFileFilter(
288
                    Project.FILE_EXTENSION, MessageFormat.format(PluginServices
289
                            .getText(this, "tipo_fichero_proyecto"),
290
                            Project.FILE_EXTENSION));
291
            jfc.addChoosableFileFilter(projExtensionFilter);
292
            jfc.setFileFilter(projExtensionFilter);
293
            
294
            if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
295
                return saved;
296
            }
297
            file = jfc.getSelectedFile();
298
        }
299

    
300
        if (!(file.getPath().toLowerCase().endsWith(Project.FILE_EXTENSION
301
                .toLowerCase()))) {
302
            file = new File(file.getPath() + Project.FILE_EXTENSION);
303
        }
304
        saved = writeProject(file, p);
305
        String filePath = file.getAbsolutePath();
306
        lastSavePath = FilenameUtils.getPath(filePath);
307

    
308
        getProjectFrame().setProject(p);
309
        return saved;
310
    }
311

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

    
345
    @Override
346
    public void execute(String command) {
347
        this.execute(command, null);
348
    }
349

    
350
    @Override
351
    public void execute(String actionCommand, Object[] args) {
352
        switch (actionCommand) {
353
            case "application-project-new":
354
                if (!askSave()) {
355
                    return;
356
                }   projectPath = null;
357
                PluginServices.getMDIManager().closeAllWindows();
358
                setProject(ProjectManager.getInstance().createProject());
359
                showProjectWindow();
360
                PluginServices.getMainFrame().setTitle(PluginServices.getText(this, "sin_titulo"));
361
                break;
362
            case "application-project-open":
363
                if (!askSave()) {
364
                    return;
365
                }   setProject(ProjectManager.getInstance().createProject());
366
                File projectFile = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
367
                if (projectFile != null && !projectFile.exists()) {
368
                    LOG.warn("Can't load project '" + projectFile.getAbsolutePath() + "', file not exist.");
369
                    projectFile = null;
370
                }   if (projectFile == null) {
371
                    FileDialogChooserManager fileDialogChooserManager = ToolsUtilLocator.getFileDialogChooserManager();
372
                    FileDialogChooser jfc = fileDialogChooserManager.create(PROJECT_FILE_CHOOSER_ID);
373
                    if (lastSavePath == null) {
374
                        jfc.setCurrentDirectory(getPreferredProjectsFolder());
375
                    } else {
376
                        jfc.setCurrentDirectory(new File(lastSavePath));
377
                    }
378
                    ProjectPreviewPanel preview = new ProjectPreviewPanel();
379
                    jfc.setAccessory(preview);
380
                    jfc.addPropertyChangeListener(preview);
381
                    
382
                    GenericFileFilter projExtensionFilter
383
                            = new GenericFileFilter(Project.FILE_EXTENSION, PluginServices.getText(this, "tipo_fichero_proyecto"));
384
                    jfc.addChoosableFileFilter(projExtensionFilter);
385
                    GenericFileFilter bakExtensionFilter
386
                            = new GenericFileFilter(Project.FILE_BAK, PluginServices.getText(this, "tipo_fichero_proyecto_bak"));
387
                    jfc.addChoosableFileFilter(bakExtensionFilter);
388
                    jfc.setFileFilter(projExtensionFilter);
389
                    
390
                    if (jfc.showOpenDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
391
                        return;
392
                    }
393
                    projectFile = jfc.getSelectedFile();
394
                }   PluginServices.getMDIManager().closeAllWindows();
395
                Project o = readProject(projectFile);
396
                if ("bak".equals(FilenameUtils.getExtension(projectFile.getAbsolutePath()))) {
397
                    setPath(null);
398
                } else {
399
                    setPath(projectFile.getAbsolutePath());
400
                }   // lastPath = getPath();
401
                if (o != null) {
402
                    setProject(o);
403
                }   getProjectFrame().setProject(p);
404
                PluginServices.getMainFrame().setTitle(projectFile.getName());
405
                
406
                break;
407
            case "application-project-save":
408
                // saveProject();
409
                try {
410
                    Launcher.manageUnsavedData("there_are_unsaved_resources");
411
                } catch (Exception e) {
412
                    LOG.warn("Can't manage unsaved data", e);
413
                }   break;
414
            case "application-project-save-as":
415
                File file = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
416
                saveAsProject(file);
417
                break;
418
            default:
419
                break;
420
        }
421

    
422
    }
423

    
424
    private File getPreferredProjectsFolder() throws LocatorException {
425
        Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
426
        FoldersManager folderManager = ToolsLocator.getFoldersManager();
427
        String v;
428
        
429
        v = prefs.get(InitializeApplicationExtension.PROJECTS_FOLDER_PROPERTY_NAME, folderManager.getHome().getAbsolutePath());
430
        return new File(v);
431
    }
432

    
433
    private void createEmptyProject() {
434
        setProject(ProjectManager.getInstance().createProject());
435
        p.setName(PluginServices.getText(this, "untitled"));
436
        p.setModified(false);
437
        PluginServices.getMainFrame().setTitle(
438
                PluginServices.getText(this, "sin_titulo"));
439
        setProject(p);
440
        showProjectWindow();
441
    }
442

    
443
    @Override
444
    public void postInitialize() {
445
        PluginsManager pluginsManager = PluginsLocator.getManager();
446
        pluginsManager.addStartupTask("createEmptyProject", () -> {
447
            createEmptyProject();
448
        },
449
                true,
450
                1000
451
        );
452
    }
453

    
454
    /**
455
     * Escribe el proyecto en XML.
456
     *
457
     * @param file Fichero.
458
     * @param p Proyecto.
459
     * @return 
460
     */
461
    public boolean writeProject(File file, Project p) {
462
        return writeProject(file, p, true);
463
    }
464

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

    
496
            PluginServices.getMainFrame().setTitle(file.getName());
497
            setPath(file.toString());
498

    
499
        } catch (LocatorException e) {
500
            application.messageDialog(
501
                    i18n.getTranslation("_Problems_saving_the_project_XnlX_It_is_possible_that_this_was_not_saved_properly_and_can_not_be_loaded_again"),
502
                    null,
503
                    i18n.getTranslation("guardar"),
504
                    JOptionPane.ERROR_MESSAGE,
505
                    "Problems_saving_the_project"
506
            );
507
            LOG.warn("Error writing project '" + file.getAbsolutePath() + "'.", e);
508
            return false;
509
        }
510
        LOG.warn("Wrote project '" + file.getAbsolutePath() + "'.");
511
        return true;
512
    }
513

    
514
    boolean isValidZIP(final File file) {
515
        ZipFile zipfile = null;
516
        try {
517
            zipfile = new ZipFile(file);
518
            return true;
519
        } catch (IOException e) {
520
            return false;
521
        } finally {
522
            try {
523
                if (zipfile != null) {
524
                    zipfile.close();
525
                }
526
            } catch (IOException e) {
527
            }
528
        }
529
    }
530

    
531
    private BufferedImage scale(BufferedImage before, double factor) {
532
        int w = (int) (before.getWidth() * factor);
533
        int h = (int) (before.getHeight() * factor);
534
        BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
535
        AffineTransform at = new AffineTransform();
536
        at.scale(factor, factor);
537
        AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
538
        after = scaleOp.filter(before, after);
539
        return after;
540
    }
541

    
542
    public Project readProject(String path) {
543
        Project project = ProjectManager.getInstance().createProject();
544

    
545
        project.loadState(new File(path));
546
        return (Project) project;
547
    }
548

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

    
577
        project.loadState(file);
578
        Set<String> unloadedObjects = project.getUnloadedObjects();
579
        List<Exception> errors = project.getLoadErrors();
580

    
581
        if (!CollectionUtils.isEmpty(unloadedObjects)) {
582
            StringBuilder builder = new StringBuilder();
583
            builder.append("Unloaded elements loading the project:\n");
584
            Iterator<String> it = unloadedObjects.iterator();
585
            while (it.hasNext()) {
586
                builder.append("\t");
587
                builder.append(it.next());
588
                builder.append("\n");
589
            }
590

    
591
            LOG.warn(builder.toString());
592
        }
593
        if (!CollectionUtils.isEmpty(unloadedObjects) || !CollectionUtils.isEmpty(errors)) {
594
            ApplicationManager application = ApplicationLocator.getManager();
595
            I18nManager i18nManager = ToolsLocator.getI18nManager();
596

    
597
            application.messageDialog(
598
                    i18nManager.getTranslation("_some_project_elements_could_not_be_loaded") + "\n"
599
                    + i18nManager.getTranslation("_maybe_you_need_to_install_any_plugins") + "\n"
600
                    + i18nManager.getTranslation("_Recovered_data_may_be_corrupted") + "\n\n"
601
                    + i18nManager.getTranslation("_see_error_log_for_more_information"),
602
                    i18nManager.getTranslation("warning"),
603
                    JOptionPane.WARNING_MESSAGE);
604

    
605
        } else {
606

    
607
        }
608
        return (Project) project;
609
    }
610

    
611
    /**
612
     * Devuelve el proyecto.
613
     *
614
     * @return Proyecto.
615
     */
616
    public Project getProject() {
617
        return p;
618
    }
619

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

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

    
636
    /**
637
     * Sets the project
638
     *
639
     * @param p
640
     */
641
    public void setProject(Project p) {
642
        this.p = p;
643
        getProjectFrame().setProject(p);
644
    }
645

    
646
    private void registerDocuments() {
647
        ViewManager.register();
648
    }
649

    
650
    private void initializeDocumentActionsExtensionPoint() {
651
        ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
652
        epMan.add(
653
                "DocumentActions_View",
654
                "Context menu options of the view document list"
655
                + " in the project window "
656
                + "(register instances of "
657
                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
658
    }
659

    
660
    public static String getPath() {
661
        return projectPath;
662
    }
663

    
664
    public static void setPath(String path) {
665
        projectPath = path;
666
    }
667

    
668
    public IWindow getProjectWindow() {
669
        return getProjectFrame();
670
    }
671

    
672
    @Override
673
    public IExtensionStatus getStatus() {
674
        return this;
675
    }
676

    
677
    @Override
678
    public boolean hasUnsavedData() {
679
        return p.hasChanged();
680
    }
681

    
682
    @Override
683
    public IUnsavedData[] getUnsavedData() {
684
        if (hasUnsavedData()) {
685
            UnsavedProject data = new UnsavedProject(this);
686
            IUnsavedData[] dataArray = {data};
687
            return dataArray;
688
        } else {
689
            return null;
690
        }
691
    }
692

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

    
701
        public UnsavedProject(IExtension extension) {
702
            super(extension);
703
        }
704

    
705
        @Override
706
        public String getDescription() {
707
            if (getPath() == null) {
708
                return PluginServices.getText(ProjectExtension.this,
709
                        "Unnamed_new_gvsig_project_");
710
            } else {
711
                return PluginServices.getText(ProjectExtension.this,
712
                        "Modified_project_");
713
            }
714
        }
715

    
716
        @Override
717
        public String getResourceName() {
718
            if (getPath() == null) {
719
                return PluginServices.getText(ProjectExtension.this, "_Project_not_saved");
720
            } else {
721
                return getPath();
722
            }
723

    
724
        }
725

    
726
        @Override
727
        public boolean saveData() {
728
            return saveProject();
729
        }
730

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

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

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

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

    
771
    /**
772
     * Adds the specified after saving listener to receive "after saving file
773
     * events" from this component. If l is null, no exception is thrown and no
774
     * action is performed.
775
     *
776
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
777
     *
778
     * @param l 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 the before saving listener
840
     * @see SaveEvent
841
     * @see BeforeSavingListener
842
     * @see #addListener(BeforeSavingListener)
843
     * @see #getBeforeSavingListeners()
844
     */
845
    public synchronized void removeListener(BeforeSavingListener l) {
846
        if (l == null) {
847
            return;
848
        }
849

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

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

    
873
        this.afterSavingListeners.remove(l);
874
    }
875

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

    
888
        Iterator<BeforeSavingListener> iter = this.beforeSavingListeners
889
                .iterator();
890

    
891
        while (iter.hasNext()) {
892
            iter.next().beforeSaving(evt);
893
        }
894
    }
895

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

    
910
        while (iter.hasNext()) {
911
            iter.next().afterSaving(evt);
912
        }
913

    
914
    }
915
}