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

History | View | Annotate | Download (24.6 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.io.File;
28
import java.text.MessageFormat;
29
import java.util.ArrayList;
30
import java.util.Iterator;
31
import java.util.List;
32
import java.util.prefs.Preferences;
33

    
34
import javax.swing.JOptionPane;
35

    
36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.andami.IconThemeHelper;
40
import org.gvsig.andami.Launcher;
41
import org.gvsig.andami.Launcher.TerminationProcess;
42
import org.gvsig.andami.PluginServices;
43
import org.gvsig.andami.messages.NotificationManager;
44
import org.gvsig.andami.plugins.Extension;
45
import org.gvsig.andami.plugins.IExtension;
46
import org.gvsig.andami.plugins.status.IExtensionStatus;
47
import org.gvsig.andami.plugins.status.IUnsavedData;
48
import org.gvsig.andami.plugins.status.UnsavedData;
49
import org.gvsig.andami.ui.mdiManager.IWindow;
50
import org.gvsig.andami.ui.mdiManager.WindowInfo;
51
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
52
import org.gvsig.app.project.Project;
53
import org.gvsig.app.project.ProjectManager;
54
import org.gvsig.app.project.documents.gui.ProjectWindow;
55
import org.gvsig.app.project.documents.view.ViewManager;
56
import org.gvsig.gui.beans.swing.JFileChooser;
57
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
59
import org.gvsig.tools.persistence.exception.PersistenceException;
60
import org.gvsig.utils.GenericFileFilter;
61
import org.gvsig.utils.save.AfterSavingListener;
62
import org.gvsig.utils.save.BeforeSavingListener;
63
import org.gvsig.utils.save.SaveEvent;
64
import org.gvsig.utils.swing.threads.IMonitorableTask;
65

    
66
/**
67
 * Extension que proporciona controles para crear proyectos nuevos, abrirlos y
68
 * guardarlos. Adem?s los tipos de tabla que soporta el proyecto son a?adidos
69
 * en esta clase.
70
 * 
71
 * @author Fernando Gonz?lez Cort?s
72
 */
73
public class ProjectExtension extends Extension implements IExtensionStatus {
74
    private static final Logger LOG =
75
        LoggerFactory.getLogger(ProjectExtension.class);
76
    
77
    private static String projectPath = null;
78
    private ProjectWindow projectFrame;
79
    private Project p;
80
    private String lastSavePath;
81
    private WindowInfo seedProjectWindow;
82
    public static final String PROJECT_FILE_CHOOSER_ID =
83
        "PROJECT_FILECHOOSER_ID";
84
    /**
85
     * Use UTF-8 for encoding, as it can represent characters from
86
     * any language.
87
     * 
88
     * Another sensible option would be
89
     * encoding = System.getProperty("file.encoding");
90
     * but this would need some extra testing.
91
     * 
92
     * @deprecated see PersistentManager
93
     */
94
    public static String PROJECTENCODING = "UTF-8";
95

    
96
    private List<BeforeSavingListener> beforeSavingListeners =
97
        new ArrayList<BeforeSavingListener>();
98

    
99
    private List<AfterSavingListener> afterSavingListeners =
100
        new ArrayList<AfterSavingListener>();
101

    
102
    /**
103
     * @see com.iver.mdiApp.plugins.IExtension#initialize()
104
     */
105
    public void initialize() {
106
        try {
107
            Class.forName("javax.media.jai.EnumeratedParameter");
108
        } catch (ClassNotFoundException e) {
109
            NotificationManager
110
                .addError(
111
                    "La m?quina virtual con la que se ejecuta gvSIG no tiene JAI instalado",
112
                    e);
113
        }
114

    
115
        initializeDocumentActionsExtensionPoint();
116
        registerIcons();
117
    }
118

    
119
    private void registerIcons() {
120
            IconThemeHelper.registerIcon("action", "application-project-new", this);
121
            IconThemeHelper.registerIcon("action", "application-project-open", this);
122
            IconThemeHelper.registerIcon("action", "application-project-save", this);
123
            IconThemeHelper.registerIcon("action", "application-project-save-as", this);
124
            IconThemeHelper.registerIcon("action", "application-exit", this);
125
            
126
        IconThemeHelper.registerIcon("project", "project-icon", this);
127
    }
128

    
129
    private void loadInitialProject() {
130
        String[] theArgs = PluginServices.getArguments();
131
        String lastArg = theArgs[theArgs.length - 1];
132
        if ((lastArg.toLowerCase().endsWith(Project.FILE_EXTENSION
133
            .toLowerCase()))) {
134
            PluginServices.getLogger().debug(
135
                "Intentando cargar el proyecto " + lastArg);
136
            // File projectFile = new File(lastArg);
137
            setProject(readProject(lastArg));
138
            
139
            int last_bar = lastArg.lastIndexOf(File.separator);
140
            String tit = lastArg.substring(last_bar);
141
            
142
            PluginServices.getMainFrame().setTitle(tit);
143
            projectPath = lastArg;
144
        } else {
145
            setProject(ProjectManager.getInstance().createProject());
146
            p.setName(PluginServices.getText(this, "untitled"));
147
            p.setModified(false);
148
            PluginServices.getMainFrame().setTitle(
149
                PluginServices.getText(this, "sin_titulo"));
150
        }
151

    
152
    }
153

    
154
    /**
155
     * @see com.iver.mdiApp.plugins.IExtension#postInitialize()
156
     */
157
    public void postInitialize() {
158
        registerDocuments();
159
        loadInitialProject();
160
        getProjectFrame().setProject(p);
161
        showProjectWindow();
162
    }
163

    
164
    public ProjectWindow getProjectFrame() {
165
        if (projectFrame == null) {
166
            projectFrame = new ProjectWindow();
167
        }
168
        return projectFrame;
169
    }
170

    
171
    /**
172
     * Muestra la ventana con el gestor de proyectos.
173
     */
174
    public void showProjectWindow() {
175
        if (seedProjectWindow != null) {
176
            if (seedProjectWindow.isClosed()) {
177
                // if it was closed, we just don't open the window now
178
                seedProjectWindow.setClosed(false);
179
                return;
180
            }
181
            WindowInfo winProps = seedProjectWindow;
182
            seedProjectWindow = null;
183
            PluginServices.getMDIManager().addWindow(getProjectFrame());
184
            PluginServices.getMDIManager().changeWindowInfo(getProjectFrame(),
185
                winProps);
186
        } else {
187
            PluginServices.getMDIManager().addWindow(getProjectFrame());
188
        }
189
    }
190

    
191
    /**
192
     * Muestra la ventana con el gestor de proyectos, con las propiedades
193
     * de ventana especificadas.
194
     */
195
    public void showProjectWindow(WindowInfo wi) {
196
        seedProjectWindow = wi;
197
        showProjectWindow();
198
    }
199

    
200
    /**
201
     * Guarda el proyecto actual en disco.
202
     */
203
    private boolean guardar() {
204
        boolean saved = false;
205
        // if (p.getPath() == null) {
206
        if (projectPath == null) {
207
            saved = guardarDialogo();
208
        } else {
209
            long t1, t2;
210
            t1 = System.currentTimeMillis();
211
            saved = writeProject(new File(projectPath), p, false);
212
            t2 = System.currentTimeMillis();
213
            PluginServices.getLogger().info(
214
                "Project saved. " + (t2 - t1) + " miliseconds");
215
            getProjectFrame().refreshControls();
216
        }
217
        return saved;
218
    }
219

    
220
    private boolean guardarDialogo() {
221
        boolean saved = false;
222

    
223
        if (lastSavePath == null) {
224
            lastSavePath = projectPath;
225
        }
226

    
227
        Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
228
        JFileChooser jfc =
229
            new JFileChooser(PROJECT_FILE_CHOOSER_ID, prefs.get(
230
                "ProjectsFolder", null));
231

    
232
        jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
233
        jfc.addChoosableFileFilter(new GenericFileFilter(
234
            Project.FILE_EXTENSION, MessageFormat.format(
235
                PluginServices.getText(this, "_gvSIG_file_project_({0})"),
236
                Project.FILE_EXTENSION)));
237

    
238
        if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) == JFileChooser.APPROVE_OPTION) {
239
            File file = jfc.getSelectedFile();
240
            if (!(file.getPath().toLowerCase().endsWith(Project.FILE_EXTENSION
241
                .toLowerCase()))) {
242
                file = new File(file.getPath() + Project.FILE_EXTENSION);
243
            }
244
            saved = writeProject(file, p);
245
            String filePath = file.getAbsolutePath();
246
            lastSavePath =
247
                filePath.substring(0, filePath.lastIndexOf(File.separatorChar));
248

    
249
            getProjectFrame().refreshControls();
250
        }
251
        return saved;
252
    }
253

    
254
    /**
255
     * Checks whether the project and related unsaved data is modified,
256
     * and allows the user to save it.
257
     * 
258
     * @return true if the data has been correctly saved, false otherwise
259
     */
260
    private boolean askSave() {
261
        if (p != null && p.hasChanged()) {
262
            TerminationProcess process = Launcher.getTerminationProcess();
263
            UnsavedDataPanel panel = process.getUnsavedDataPanel();
264
            panel.setHeaderText(PluginServices.getText(this,
265
                "Select_resources_to_save_before_closing_current_project"));
266
            panel.setAcceptText(PluginServices.getText(this, "save_resources"),
267
                PluginServices.getText(this,
268
                    "Save_the_selected_resources_and_close_current_project"));
269
            panel.setCancelText(PluginServices.getText(this, "Dont_close"),
270
                PluginServices.getText(this, "Return_to_current_project"));
271
            int closeCurrProj;
272
            try {
273
                closeCurrProj = process.manageUnsavedData();
274
                if (closeCurrProj == JOptionPane.NO_OPTION) {
275
                    // the user chose to return to current project
276
                    return false;
277
                }
278
            } catch (Exception e) {
279
                LOG.error("Some data can not be saved", e);
280
            }           
281
        }
282
        return true;
283
    }
284

    
285
    /**
286
     * @see com.iver.mdiApp.plugins.IExtension#updateUI(java.lang.String)
287
     */
288
    public void execute(String actionCommand) {
289
        if (actionCommand.equals("application-project-new")) {
290
            if (!askSave()) {
291
                return;
292
            }
293

    
294
            projectPath = null;
295
            // ProjectDocument.initializeNUMS();
296
            PluginServices.getMDIManager().closeAllWindows();
297
            setProject(ProjectManager.getInstance().createProject());
298
            getProjectFrame().setProject(p);
299
            showProjectWindow();
300
            PluginServices.getMainFrame().setTitle(
301
                PluginServices.getText(this, "sin_titulo"));
302
        } else
303
            if (actionCommand.equals("application-project-open")) {
304
                if (!askSave()) {
305
                    return;
306
                }
307

    
308
                Preferences prefs =
309
                    Preferences.userRoot().node("gvsig.foldering");
310
                JFileChooser jfc =
311
                    new JFileChooser(PROJECT_FILE_CHOOSER_ID, prefs.get(
312
                        "ProjectsFolder", null));
313
                jfc.addChoosableFileFilter(new GenericFileFilter(
314
                    Project.FILE_EXTENSION, PluginServices.getText(this,
315
                        "tipo_fichero_proyecto")));
316

    
317
                if (jfc.showOpenDialog((Component) PluginServices
318
                    .getMainFrame()) == JFileChooser.APPROVE_OPTION) {
319
                    // ProjectDocument.initializeNUMS();
320
                    PluginServices.getMDIManager().closeAllWindows();
321

    
322
                    File projectFile = jfc.getSelectedFile();
323
                    Project o = readProject(projectFile);
324
                    setPath(projectFile.getAbsolutePath());
325
                    // lastPath = getPath();
326
                    if (o != null) {
327
                        setProject(o);
328
                    }
329

    
330
                    getProjectFrame().setProject(p);
331
                    PluginServices.getMainFrame().setTitle(projectFile.getName());
332
                    getProjectFrame().refreshControls();
333

    
334
                    // p.restoreWindowProperties();
335
                }
336
            } else
337
                if (actionCommand.equals("application-project-save")) {
338
                    guardar();
339
                } else
340
                    if (actionCommand.equals("application-project-save-as")) {
341
                        guardarDialogo();
342
                    } else
343
                        if (actionCommand.equals("application-exit")) {
344
                            Launcher.closeApplication();
345
                        }
346
    }
347

    
348
    /**
349
     * Escribe el proyecto en XML.
350
     * 
351
     * @param file
352
     *            Fichero.
353
     * @param p
354
     *            Proyecto.
355
     */
356
    public boolean writeProject(File file, Project p) {
357
        return writeProject(file, p, true);
358
    }
359

    
360
    /**
361
     * Escribe el proyecto en XML. Pero permite decidir si se
362
     * pide confirmaci?n para sobreescribir
363
     * 
364
     * @param file
365
     *            Fichero.
366
     * @param p
367
     *            Proyecto.
368
     * @param askConfirmation
369
     *            boolean
370
     */
371
    public boolean writeProject(File file, Project p, boolean askConfirmation) {
372
        if (askConfirmation && file.exists()) {
373
            int resp =
374
                JOptionPane.showConfirmDialog((Component) PluginServices
375
                    .getMainFrame(), PluginServices.getText(this,
376
                    "fichero_ya_existe_seguro_desea_guardarlo"), PluginServices
377
                    .getText(this, "guardar"), JOptionPane.YES_NO_OPTION);
378
            if (resp != JOptionPane.YES_OPTION) {
379
                return false;
380
            }
381
        }
382
        NotificationManager.addInfo(PluginServices.getText(this,
383
            "writinng_project") + ": " + file.getName());
384

    
385
        // write it out as XML
386
        try {
387
            fireBeforeSavingFileEvent(new SaveEvent(this,
388
                SaveEvent.BEFORE_SAVING, file));
389
            p.saveState(file);
390
            fireAfterSavingFileEvent(new SaveEvent(this,
391
                SaveEvent.AFTER_SAVING, file));
392
            
393
            PluginServices.getMainFrame().setTitle(file.getName());
394
            setPath(file.toString());
395

    
396
        } catch (PersistenceException e) {
397
            String messagestack = e.getLocalizedMessageStack();
398
            NotificationManager.addError(
399
                PluginServices.getText(this, "error_writing_project") + ": "
400
                    + file.getName() + "\n" + messagestack, e);
401
            return false;
402
        } catch (Exception e) {
403
            NotificationManager.addError(
404
                PluginServices.getText(this, "error_writing_project") + ": "
405
                    + file.getName(), e);
406
            return false;
407
        }
408
        NotificationManager.addInfo(PluginServices.getText(this,
409
            "wrote_project") + ": " + file.getName());
410
        return true;
411
    }
412

    
413
    public Project readProject(String path) {
414
        Project project = ProjectManager.getInstance().createProject();
415

    
416
        project.loadState(new File(path));
417
        return (Project) project;
418
    }
419

    
420
    /**
421
     * Lee del XML el proyecto.<br>
422
     * <br>
423
     * 
424
     * Reads the XML of the project.<br>
425
     * It returns a project object holding all needed info that is not linked to
426
     * the Project Dialog. <br>
427
     * In case you want the project to be
428
     * linked to the window you must set this object to the extension:<br>
429
     * 
430
     * <b>Example:</b><br>
431
     * 
432
     * ...<br>
433
     * ...<br>
434
     * Project p = ProjectExtension.readProject(projectFile);<br>
435
     * ProjectExtension.setProject(p);
436
     * ...<br>
437
     * ...<br>
438
     * 
439
     * @param file
440
     *            Fichero.
441
     * 
442
     * @return Project
443
     * 
444
     */
445
    public Project readProject(File file) {
446
        Project project = ProjectManager.getInstance().createProject();
447

    
448
        project.loadState(file);
449
        return (Project) project;
450
    }
451

    
452
    /**
453
     * Devuelve el proyecto.
454
     * 
455
     * @return Proyecto.
456
     */
457
    public Project getProject() {
458
        return p;
459
    }
460

    
461
    /**
462
     * @see org.gvsig.andami.plugins.IExtension#isEnabled()
463
     */
464
    public boolean isEnabled() {
465
        return true;
466
    }
467

    
468
    /**
469
     * @see org.gvsig.andami.plugins.IExtension#isVisible()
470
     */
471
    public boolean isVisible() {
472
        return true;
473
    }
474

    
475
    /**
476
     * Sets the project
477
     * 
478
     * @param p
479
     */
480
    public void setProject(Project p) {
481
        getProjectFrame().setProject(p);
482
        this.p = p;
483
    }
484

    
485
    private void registerDocuments() {
486
        ViewManager.register();
487
    }
488

    
489
    private void initializeDocumentActionsExtensionPoint() {
490
        ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
491
        epMan.add("DocumentActions_View",
492
            "Context menu options of the view document list"
493
                + " in the project window " + "(register instances of "
494
                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
495
    }
496

    
497
    public static String getPath() {
498
        return projectPath;
499
    }
500

    
501
    public static void setPath(String path) {
502
        projectPath = path;
503
    }
504

    
505
    public IWindow getProjectWindow() {
506
        return getProjectFrame();
507
    }
508

    
509
    public IExtensionStatus getStatus() {
510
        return this;
511
    }
512

    
513
    public boolean hasUnsavedData() {
514
        return p.hasChanged();
515
    }
516

    
517
    public IUnsavedData[] getUnsavedData() {
518
        if (hasUnsavedData()) {
519
            UnsavedProject data = new UnsavedProject(this);
520
            IUnsavedData[] dataArray = { data };
521
            return dataArray;
522
        } else {
523
            return null;
524
        }
525
    }
526

    
527
    /**
528
     * Implements the IUnsavedData interface to show unsaved projects
529
     * in the Unsavad Data dialog.
530
     * 
531
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
532
     */
533
    public class UnsavedProject extends UnsavedData {
534

    
535
        public UnsavedProject(IExtension extension) {
536
            super(extension);
537
        }
538

    
539
        public String getDescription() {
540
            if (getPath() == null) {
541
                return PluginServices.getText(ProjectExtension.this,
542
                    "Unnamed_new_gvsig_project_");
543
            } else {
544
                return PluginServices.getText(ProjectExtension.this,
545
                    "Modified_project_");
546
            }
547
        }
548

    
549
        public String getResourceName() {
550
            if (getPath() == null) {
551
                return PluginServices.getText(ProjectExtension.this, "Unnamed");
552
            } else {
553
                return getPath();
554
            }
555

    
556
        }
557

    
558
        public boolean saveData() {
559
            return guardar();
560
        }
561

    
562
        public String getIcon() {
563
            return "project-icon";
564
        }
565
    }
566

    
567
    public IMonitorableTask[] getRunningProcesses() {
568
        // TODO Auto-generated method stub
569
        return null;
570
    }
571

    
572
    public boolean hasRunningProcesses() {
573
        // TODO Auto-generated method stub
574
        return false;
575
    }
576

    
577
    /**
578
     * Adds the specified before saving listener to receive
579
     * "before saving file events" from
580
     * this component.
581
     * If l is null, no exception is thrown and no action is performed.
582
     * 
583
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
584
     * 
585
     * @param l
586
     *            the before saving listener.
587
     * @see SaveEvent
588
     * @see BeforeSavingListener
589
     * @see #removeListener(BeforeSavingListener)
590
     * @see #getBeforeSavingListeners
591
     */
592
    public synchronized void addListener(BeforeSavingListener l) {
593
        if (l == null) {
594
            return;
595
        }
596
        if (!this.beforeSavingListeners.contains(l)) {
597
            this.beforeSavingListeners.add(l);
598
        }
599
    }
600

    
601
    /**
602
     * Adds the specified after saving listener to receive
603
     * "after saving file events" from
604
     * this component.
605
     * If l is null, no exception is thrown and no action is performed.
606
     * 
607
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
608
     * 
609
     * @param l
610
     *            the after saving listener.
611
     * @see SaveEvent
612
     * @see AfterSavingListener
613
     * @see #removeListener(AfterSavingListener)
614
     * @see #getAfterSavingListeners()
615
     */
616
    public synchronized void addListener(AfterSavingListener l) {
617
        if (l == null) {
618
            return;
619
        }
620

    
621
        if (!this.afterSavingListeners.contains(l)) {
622
            this.afterSavingListeners.add(l);
623
        }
624

    
625
    }
626

    
627
    /**
628
     * Returns an array of all the before saving listeners
629
     * registered on this component.
630
     * 
631
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
632
     * 
633
     * @return all of this component's <code>BeforeSavingListener</code>s
634
     *         or an empty array if no key
635
     *         listeners are currently registered
636
     * 
637
     * @see #addBeforeSavingListener(BeforeSavingListener)
638
     * @see #removeBeforeSavingListener(BeforeSavingListener)
639
     */
640
    public synchronized BeforeSavingListener[] getBeforeSavingListeners() {
641
        return this.beforeSavingListeners
642
            .toArray(new BeforeSavingListener[] {});
643
    }
644

    
645
    /**
646
     * Returns an array of all the after saving listeners
647
     * registered on this component.
648
     * 
649
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
650
     * 
651
     * @return all of this component's <code>AfterSavingListener</code>s
652
     *         or an empty array if no key
653
     *         listeners are currently registered
654
     * 
655
     * @see #addAfterSavingListener(AfterSavingListener)
656
     * @see #removeAfterSavingListener
657
     */
658
    public synchronized AfterSavingListener[] getAfterSavingListeners() {
659
        return this.afterSavingListeners.toArray(new AfterSavingListener[] {});
660

    
661
    }
662

    
663
    /**
664
     * Removes the specified before saving listener so that it no longer
665
     * receives save file events from this component. This method performs
666
     * no function, nor does it throw an exception, if the listener
667
     * specified by the argument was not previously added to this component.
668
     * If listener <code>l</code> is <code>null</code>,
669
     * no exception is thrown and no action is performed.
670
     * 
671
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
672
     * 
673
     * @param l
674
     *            the before saving listener
675
     * @see SaveEvent
676
     * @see BeforeSavingListener
677
     * @see #addListener(BeforeSavingListener)
678
     * @see #getBeforeSavingListeners()
679
     */
680
    public synchronized void removeListener(BeforeSavingListener l) {
681
        if (l == null) {
682
            return;
683
        }
684

    
685
        this.beforeSavingListeners.remove(l);
686
    }
687

    
688
    /**
689
     * Removes the specified after saving listener so that it no longer
690
     * receives save file events from this component. This method performs
691
     * no function, nor does it throw an exception, if the listener
692
     * specified by the argument was not previously added to this component.
693
     * If listener <code>l</code> is <code>null</code>,
694
     * no exception is thrown and no action is performed.
695
     * 
696
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
697
     * 
698
     * @param l
699
     *            the after saving listener
700
     * @see SaveEvent
701
     * @see AfterSavingListener
702
     * @see #addListener(AfterSavingListener)
703
     * @see #getAfterSavingListeners()
704
     */
705
    public synchronized void removeListener(AfterSavingListener l) {
706
        if (l == null) {
707
            return;
708
        }
709

    
710
        this.afterSavingListeners.remove(l);
711
    }
712

    
713
    /**
714
     * Reports a before saving file event.
715
     * 
716
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
717
     * 
718
     * @param evt
719
     *            the before saving file event
720
     */
721
    protected void fireBeforeSavingFileEvent(SaveEvent evt) {
722
        if ((evt.getID() != SaveEvent.BEFORE_SAVING) || (evt.getFile() == null)) {
723
            return;
724
        }
725

    
726
        Iterator<BeforeSavingListener> iter =
727
            this.beforeSavingListeners.iterator();
728

    
729
        while (iter.hasNext()) {
730
            iter.next().beforeSaving(evt);
731
        }
732
    }
733

    
734
    /**
735
     * Reports a after saving file event.
736
     * 
737
     * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
738
     * 
739
     * @param evt
740
     *            the after saving file event
741
     */
742
    protected void fireAfterSavingFileEvent(SaveEvent evt) {
743
        if ((evt.getID() != SaveEvent.AFTER_SAVING) || (evt.getFile() == null)) {
744
            return;
745
        }
746
        Iterator<AfterSavingListener> iter =
747
            this.afterSavingListeners.iterator();
748

    
749
        while (iter.hasNext()) {
750
            iter.next().afterSaving(evt);
751
        }
752

    
753
    }
754
}