Statistics
| Revision:

root / trunk / extensions / extRasterTools-SE / src / org / gvsig / rastertools / filter / FilterListener.java @ 15778

History | View | Annotate | Download (19.1 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.rastertools.filter;
20

    
21
import java.awt.Dimension;
22
import java.awt.Graphics2D;
23
import java.awt.event.ActionEvent;
24
import java.awt.event.ActionListener;
25
import java.awt.geom.AffineTransform;
26
import java.awt.geom.Dimension2D;
27
import java.awt.geom.Point2D;
28
import java.io.File;
29
import java.util.ArrayList;
30
import java.util.EventObject;
31
import java.util.Hashtable;
32

    
33
import javax.swing.JFileChooser;
34
import javax.swing.ListModel;
35

    
36
import org.gvsig.fmap.raster.layers.FLyrRasterSE;
37
import org.gvsig.gui.beans.imagenavigator.IClientImageNavigator;
38
import org.gvsig.gui.beans.incrementabletask.IncrementableTask;
39
import org.gvsig.gui.beans.propertiespanel.PropertiesComponent;
40
import org.gvsig.gui.beans.propertiespanel.PropertiesComponentListener;
41
import org.gvsig.gui.beans.propertiespanel.PropertyStruct;
42
import org.gvsig.gui.beans.treelist.event.TreeListChangeEvent;
43
import org.gvsig.gui.beans.treelist.event.TreeListEvent;
44
import org.gvsig.gui.beans.treelist.listeners.TreeListChangeListener;
45
import org.gvsig.gui.beans.treelist.listeners.TreeListComponentListener;
46
import org.gvsig.raster.dataset.GeoRasterWriter;
47
import org.gvsig.raster.dataset.IRasterDataSource;
48
import org.gvsig.raster.dataset.InvalidSetViewException;
49
import org.gvsig.raster.dataset.Params;
50
import org.gvsig.raster.dataset.Params.Param;
51
import org.gvsig.raster.datastruct.Extent;
52
import org.gvsig.raster.datastruct.ViewPortData;
53
import org.gvsig.raster.grid.filter.FilterUIListener;
54
import org.gvsig.raster.grid.filter.IRasterFilterListManager;
55
import org.gvsig.raster.grid.filter.RasterFilter;
56
import org.gvsig.raster.grid.filter.RasterFilterList;
57
import org.gvsig.raster.grid.filter.RasterFilterListManager;
58
import org.gvsig.raster.grid.filter.RegistrableFilterListener;
59
import org.gvsig.raster.hierarchy.IRasterRendering;
60
import org.gvsig.raster.util.RasterNotLoadException;
61
import org.gvsig.raster.util.RasterToolsUtil;
62
import org.gvsig.rastertools.RasterModule;
63
import org.gvsig.rastertools.filter.ui.FilterPanel;
64

    
65
import com.iver.andami.PluginServices;
66
import com.iver.andami.Utilities;
67
import com.iver.andami.messages.NotificationManager;
68
import com.iver.cit.gvsig.addlayer.fileopen.FileOpenWizard;
69
import com.iver.cit.gvsig.fmap.ViewPort;
70
import com.iver.cit.gvsig.fmap.layers.FLayer;
71
/**
72
 * <code>FilterListener</code> es la clase donde se procesar? gran parte del
73
 * c?digo que controla el panel para el manejo de un layer en la aplicaci?n de
74
 * filtros.
75
 *
76
 * @version 24/05/2007
77
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
78
 */
79
public class FilterListener implements ActionListener, IClientImageNavigator, TreeListComponentListener, TreeListChangeListener, PropertiesComponentListener, FilterUIListener {
80
        private FilterPanel  filterPanel  = null;
81
        private int          actualParam  = -1;
82
        private ArrayList    paramsList   = new ArrayList();
83
        private FLyrRasterSE previewLayer = null;
84

    
85
        public class ParamStruct {
86
                String filterName = null;
87
                Params filterParam = null;
88
                Class filterClass = null;
89

    
90
                /**
91
                 * @return the filterName
92
                 */
93
                public String getFilterName() {
94
                        return filterName;
95
                }
96

    
97
                /**
98
                 * @param filterName the filterName to set
99
                 */
100
                public void setFilterName(String filterName) {
101
                        this.filterName = filterName;
102
                }
103

    
104
                /**
105
                 * @return the filterParam
106
                 */
107
                public Params getFilterParam() {
108
                        return filterParam;
109
                }
110

    
111
                /**
112
                 * @param filterParam the filterParam to set
113
                 */
114
                public void setFilterParam(Params filterParam) {
115
                        this.filterParam = filterParam;
116
                }
117

    
118
                /**
119
                 * @return the filterClass
120
                 */
121
                public Class getFilterClass() {
122
                        return filterClass;
123
                }
124

    
125
                /**
126
                 * @param filterClass the filterClass to set
127
                 */
128
                public void setFilterClass(Class filterClass) {
129
                        this.filterClass = filterClass;
130
                }
131
        }
132

    
133
        /**
134
         * Construye un FilterListener especificando el FilterPanel asociado
135
         * @param fp
136
         */
137
        public FilterListener(FilterPanel fp) {
138
                filterPanel = fp;
139
        }
140

    
141
        /**
142
         * Asigna la capa raster de la vista
143
         * @param fLayer
144
         */
145
        public void setLayer(FLayer fLayer) {
146
                if (fLayer instanceof FLyrRasterSE) {
147
                        try {
148
                                previewLayer = (FLyrRasterSE) fLayer.cloneLayer();
149
                        } catch (Exception e) {
150
                                RasterToolsUtil.messageBoxError("preview_not_available", filterPanel, e);
151
                        }
152
                }
153
        }
154

    
155
        /**
156
         * Asignamos los valores del PropertiesComponent al Params seleccionado
157
         */
158
        public void RefreshDataProperties() {
159
                if (actualParam == -1) 
160
                        return;
161

    
162
                ArrayList listValues = getFilterPanel().getPropertiesComponent().getValues();
163
                
164
                Params params = ((ParamStruct) paramsList.get(actualParam)).getFilterParam();
165
                for (int j = 0; j < listValues.size(); j++) {
166
                        PropertyStruct ps = (PropertyStruct) listValues.get(j);
167
                        params.changeParamValue(ps.getKey(), ps.getNewValue());
168
                }
169
        }
170

    
171
        /**
172
         * Obtener la posici?n del Param seleccionado en el ArrayList
173
         * @param filterName
174
         * @return
175
         */
176
        private int getParamSelected(String filterName) {
177
                for (int i = 0; i < paramsList.size(); i++) {
178
                        if (((ParamStruct) paramsList.get(i)).getFilterName().equals(filterName))
179
                                return i;
180
                }
181
                return -1;
182
        }
183

    
184
        /**
185
         * Cambiar el panel de propiedades central por el nuevo panel, segun el filtro
186
         * seleccionado que se pasa por par?metro.
187
         * @param filter
188
         */
189
        public void changePanel(String filter) {
190
                int posParam = getParamSelected(filter);
191

    
192
                RefreshDataProperties();
193
                actualParam = posParam;
194

    
195
                PropertiesComponent propertiesComponent = new PropertiesComponent();
196

    
197
                if (posParam != -1) {
198
                        Params params = ((ParamStruct) paramsList.get(actualParam)).getFilterParam();
199
                        if (params != null) {
200
                                Param paramPanel = params.getParamById("Panel");
201
                                if(paramPanel != null && paramPanel.defaultValue instanceof RegistrableFilterListener)
202
                                        ((RegistrableFilterListener)paramPanel.defaultValue).addFilterUIListener(this);
203
                                RasterToolsUtil.loadPropertiesFromWriterParams(propertiesComponent, params, new String[]{"FilterName"});
204
                        }
205
                }
206
                getFilterPanel().setNewPropertiesComponent(propertiesComponent, filter);
207
        }
208

    
209
        /**
210
         * A?adir un nuevo Params a la lista de Params que podemos manejar. Un Params
211
         * equivale a un filtro cargado. El hecho de trabajar con Params y no con
212
         * filtros, simplifica totalmente el panel. Sin tener que depender de los
213
         * filtros nada m?s que para el momento de dibujado o guardado.
214
         * @param name
215
         * @param params
216
         * @param classFilter
217
         */
218
        public void addNewParam(String name, Params params, Class classFilter) {
219
                ParamStruct param = new ParamStruct();
220
                param.setFilterName(name);
221
                param.setFilterParam(params);
222
                param.setFilterClass(classFilter);
223
                paramsList.add(param);
224
        }
225

    
226
        /*
227
         * (non-Javadoc)
228
         * @see org.gvsig.gui.beans.propertiespanel.PropertiesComponentListener#actionChangeProperties(java.util.EventObject)
229
         */
230
        public void actionChangeProperties(EventObject e) {
231
                RefreshDataProperties();
232
                getFilterPanel().refreshPreview();
233
        }
234

    
235
        /*
236
         * (non-Javadoc)
237
         * @see org.gvsig.gui.beans.treelist.listeners.TreeListChangeListener#actionChangeSelection(org.gvsig.gui.beans.treelist.event.TreeListChangeEvent)
238
         */
239
        public void actionChangeSelection(TreeListChangeEvent e) {
240
                changePanel(e.getItem());
241
        }
242

    
243
        /*
244
         * (non-Javadoc)
245
         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
246
         */
247
        public void actionPerformed(ActionEvent e) {
248
                getFilterPanel().refreshPreview();
249
        }
250

    
251
        /*
252
         * (non-Javadoc)
253
         * @see org.gvsig.gui.beans.treelist.listeners.TreeListComponentListener#elementAdded(org.gvsig.gui.beans.treelist.event.TreeListEvent)
254
         */
255
        public void elementAdded(TreeListEvent e) {
256
                getFilterPanel().refreshPreview();
257
        }
258

    
259
        /*
260
         * (non-Javadoc)
261
         * @see org.gvsig.gui.beans.treelist.listeners.TreeListComponentListener#elementMoved(org.gvsig.gui.beans.treelist.event.TreeListEvent)
262
         */
263
        public void elementMoved(TreeListEvent e) {
264
                getFilterPanel().refreshPreview();
265
        }
266

    
267
        /*
268
         * (non-Javadoc)
269
         * @see org.gvsig.gui.beans.treelist.listeners.TreeListComponentListener#elementRemoved(org.gvsig.gui.beans.treelist.event.TreeListEvent)
270
         */
271
        public void elementRemoved(TreeListEvent e) {
272
                getFilterPanel().refreshPreview();
273
        }
274

    
275
        /**
276
         * @return the paramsList
277
         */
278
        public ArrayList getParamsList() {
279
                return paramsList;
280
        }
281

    
282
        /**
283
         * Devuelve la ruta del fichero donde se va a guardar, en caso de guardarse
284
         * en memoria, calcula el nombre sin preguntar y devuelve la ruta.
285
         * @return
286
         */
287
        public String getFileSelected() {
288
                String path = "";
289
                if (getFilterPanel().getRadioFileGenerate().isSelected()) {
290
                        JFileChooser chooser = new JFileChooser(FileOpenWizard.getLastPath());
291
                        chooser.setDialogTitle(PluginServices.getText(this, "seleccionar_fichero"));
292

    
293
                        //A?adimos las extensiones que hayan sido registradas en el driver
294
                        String[] extList = GeoRasterWriter.getDriversExtensions();
295
                        for(int i=0;i<extList.length;i++)
296
                                chooser.addChoosableFileFilter(new WriterFilter(extList[i]));
297

    
298
                        if (chooser.showOpenDialog(getFilterPanel()) != JFileChooser.APPROVE_OPTION)
299
                                return null;
300

    
301
                        String fName = chooser.getSelectedFile().toString();
302
                        String ext = ((WriterFilter)chooser.getFileFilter()).getDescription();
303

    
304
                        ext = ext.toLowerCase().substring(ext.lastIndexOf(".") + 1, ext.length());
305

    
306
                        if ((fName != null) && !fName.equals(""))
307
                                if (!fName.endsWith("." + ext))
308
                                        fName = fName + "." + ext;
309

    
310
                        FileOpenWizard.setLastPath(chooser.getSelectedFile().getPath().substring(0, chooser.getSelectedFile().getPath().lastIndexOf(File.separator)));
311
                        path = fName;
312
                } else {
313
                        path = Utilities.createTempDirectory() + File.separator + getFilterPanel().getFilenameTextField().getText() + ".tif";
314
                        filterPanel.setNewLayerText();
315
                }
316
                return path;
317
        }
318

    
319
        /**
320
         * Aqui se seleccionan que filtros se van a aplicar y se devuelven en forma
321
         * de ArrayList tanto para el dibujado como cuando aceptan o aplican el panel.
322
         * @param rendering
323
         * @return
324
         */
325
        public ArrayList applyFilters(IRasterRendering rendering) {
326
                ArrayList listFilterUsed = new ArrayList();
327

    
328
                RasterFilterList filterList = new RasterFilterList();
329
                filterList.setEnv(rendering.getRenderFilterList().getEnv());
330
                RasterFilterListManager stackManager = new RasterFilterListManager(filterList);
331

    
332
                // Conservamos filtros no visibles ya existentes
333
                ArrayList filtersInit = getFilterPanel().getFilterStatus();
334
                for (int i = 0; i < filtersInit.size(); i++) {
335
                        // Si es visible no hacemos nada
336
                        if (((RasterFilter) filtersInit.get(i)).isVisible())
337
                                continue;
338

    
339
                        RasterFilter obj = null;
340
                        for (int j = 0; j < stackManager.getRasterFilterList().size(); j++) {
341
                                Class classFilter = (Class) stackManager.getRasterFilterList().get(j);
342
                                try {
343
                                        obj = (RasterFilter) classFilter.newInstance();
344
                                        if (obj.getName().equals(((RasterFilter) filtersInit.get(i)).getName()))
345
                                                break;
346
                                } catch (InstantiationException e) {
347
                                        RasterToolsUtil.messageBoxError("error_creando_filtro", this, e);
348
                                } catch (IllegalAccessException e) {
349
                                        RasterToolsUtil.messageBoxError("error_creando_filtro", this, e);
350
                                }
351
                        }
352

    
353
                        // Si no encontramos el filtro apropiado, nos olvidamos de el
354
                        if (obj == null)
355
                                continue;
356

    
357
                        // Si no es visible tenemos que conservar el filtro
358
                        try {
359
                                Params params = (Params) ((RasterFilter) filtersInit.get(i)).getUIParams(((RasterFilter) filtersInit.get(i)).getName()).clone();
360
                                // A?ado el parametro RenderBands a los parametros del filtro
361
                                String rgb = rendering.getRenderBands()[0] + " " + rendering.getRenderBands()[1] + " " + rendering.getRenderBands()[2];
362
                                params.setParam("RenderBands", rgb, 0, null);
363

    
364
                                ParamStruct newParam = new ParamStruct();
365
                                newParam.setFilterClass(obj.getClass());
366
                                newParam.setFilterName(((RasterFilter) filtersInit.get(i)).getName());
367
                                newParam.setFilterParam(params);
368
                                listFilterUsed.add(newParam);
369
                        } catch (CloneNotSupportedException e) {
370
                        }
371
                }
372

    
373
                // Metemos los filtros seleccionados en el panel
374
                ListModel list = getFilterPanel().getTreeListContainer().getListModel();
375
                for (int i = 0; i < list.getSize(); i++) {
376
                        Hashtable hastTable = getFilterPanel().getTreeListContainer().getMap();
377
                        for (int j = 0; j < paramsList.size(); j++) {
378
                                boolean active = true;
379
                                Param param = ((ParamStruct) paramsList.get(j)).getFilterParam().getParamById(PluginServices.getText(this, "enabled"));
380
                                if ((param != null) && 
381
                                        param.defaultValue instanceof Boolean && 
382
                                        ((((Boolean)param.defaultValue).booleanValue()) == false))
383
                                        active = false;
384
                                if (active) {
385
                                        if (((ParamStruct) paramsList.get(j)).getFilterName().equals(hastTable.get(list.getElementAt(i)))) {
386
                                                try {
387
                                                        Params params = (Params) ((ParamStruct) paramsList.get(j)).getFilterParam().clone();
388
                                                        // A?ado el parametro RenderBands a los parametros del filtro
389
                                                        String rgb = rendering.getRenderBands()[0] + " " + rendering.getRenderBands()[1] + " " + rendering.getRenderBands()[2];
390
                                                        params.setParam("RenderBands", rgb, 0, null);
391

    
392
                                                        ParamStruct newParam = new ParamStruct();
393
                                                        newParam.setFilterClass(((ParamStruct) paramsList.get(j)).getFilterClass());
394
                                                        newParam.setFilterName(((ParamStruct) paramsList.get(j)).getFilterName());
395
                                                        newParam.setFilterParam(params);
396
                                                        listFilterUsed.add(newParam);
397
                                                } catch (CloneNotSupportedException e) {
398
                                                }
399
                                        }
400
                                }
401
                        }
402
                }
403
                return listFilterUsed;
404
        }
405

    
406
        /*
407
         * (non-Javadoc)
408
         * @see org.gvsig.gui.beans.imagenavigator.IClientImageNavigator#drawImage(java.awt.Graphics2D, double, double, double, double, double, int, int)
409
         */
410
        public void drawImage(Graphics2D g, double x1, double y1, double x2, double y2, double zoom, int width, int height) {
411
                if (previewLayer == null || !(previewLayer instanceof IRasterRendering))
412
                        return;
413

    
414
                IRasterRendering rendering = ((IRasterRendering) previewLayer);                
415
                
416
                ((FLyrRasterSE) getFilterPanel().getLayer()).setRenderBands(((FLyrRasterSE) getFilterPanel().getLayer()).getRenderBands());
417

    
418
                if ((rendering == null) || ((x2 - x1) == 0.0) || ((y2 - y1) == 0.0))
419
                        return;
420

    
421
                rendering.getRenderFilterList().pushStatus();
422

    
423
                rendering.getRenderFilterList().clear();
424

    
425
                if (getFilterPanel().getCBShowFilters().isSelected()) {
426
                        RasterFilterList filterList = rendering.getRenderFilterList();
427
                        RasterFilterListManager stackManager = new RasterFilterListManager(filterList);
428

    
429
                        ArrayList listFilterUsed = applyFilters(rendering);
430
                        for (int i = 0; i < listFilterUsed.size(); i++) {
431
                                IRasterFilterListManager filterManager = stackManager.getManagerByFilterClass(((ParamStruct) listFilterUsed.get(i)).getFilterClass());
432
                                filterManager.addFilter(((ParamStruct) listFilterUsed.get(i)).getFilterClass(), ((ParamStruct) listFilterUsed.get(i)).getFilterParam());
433
                        }
434
                }
435

    
436
                ViewPort vp = new ViewPort(null);
437

    
438
                Dimension2D dimension = new Dimension(width, height);
439
                Extent extent = new Extent(new Point2D.Double(x1, y1), new Point2D.Double(x2, y2), new Point2D.Double(x2, y1), new Point2D.Double(x1, y2));
440
                //Extent extent = new Extent(x1, y1, x2, y2);
441

    
442
                ViewPortData vp2 = new ViewPortData(vp.getProjection(), extent, dimension);
443
                vp2.setMat(new AffineTransform(zoom, 0.0, 0.0, zoom, -x1*zoom, -y1*zoom));
444

    
445
                Extent extent2 = ((FLyrRasterSE) getFilterPanel().getLayer()).getBufferFactory().getExtent();
446

    
447
                AffineTransform trans = g.getTransform();
448
                // Calcular cuanto sobresale la imagen y rectificar ese desplazamiento
449
                if (y1 > extent2.maxY()) {
450
                        g.translate(0.0, (-(extent2.maxY() - y1) * zoom)*2.0);
451
                }
452

    
453
                try {
454
                        previewLayer.getRender().draw(g, vp2);
455
                } catch (ArrayIndexOutOfBoundsException e) {
456
                        NotificationManager.addError("Error en el renderizado de la mini-imagen del panel de tabla de color.", e);
457
                } catch (InvalidSetViewException e) {
458
                        NotificationManager.addError("Error asignando la vista en el renderizado de la mini-imagen del panel de tabla de color.", e);
459
                } catch (InterruptedException e) {
460
                        NotificationManager.addWarning("Dibujado de la preview detenido por el usuario.", e);
461
                }
462
                g.setTransform(trans);
463

    
464
                rendering.getRenderFilterList().popStatus();
465
        }
466

    
467
        /**
468
         * Que acciones se ejecutaran al haber presionado el bot?n aceptar o aplicar
469
         */
470
        public void accept() {
471
                IRasterDataSource raster = ((FLyrRasterSE) getFilterPanel().getLayer()).getDataSource();
472
                if (raster == null)
473
                        return;
474

    
475
                String path = null;
476
                if (!getFilterPanel().getRadioOnlyView().isSelected()) {
477
                        path = getFileSelected();
478
                        if (path == null)
479
                                return;
480
                }
481

    
482
//                Rendering rendering = ((FLyrRasterSE) getFilterPanel().getLayer()).getRender();
483
                IRasterRendering rendering = (IRasterRendering) getFilterPanel().getLayer();
484

    
485
                // Array para guardar los filtros que se van a usar en forma de ParamStruct
486
                ArrayList listFilterUsed = applyFilters(rendering);
487

    
488
                if (filterPanel.getRadioOnlyView().isSelected()) {
489
                        FilterProcess.addSelectedFilters(rendering.getRenderFilterList(), listFilterUsed);
490
                        ((FLyrRasterSE) getFilterPanel().getLayer()).setRenderFilterList(rendering.getRenderFilterList());
491
                        getFilterPanel().getLayer().getMapContext().invalidate();
492
                } else {
493
                        FilterProcess filterProcess = new FilterProcess(this, path, raster, listFilterUsed);
494
                        IncrementableTask incrementableTask = new IncrementableTask(filterProcess);
495
                        filterProcess.setIncrementableTask(incrementableTask);
496
                        incrementableTask.showWindow();
497

    
498
                        filterProcess.start();
499
                        incrementableTask.start();
500
                }
501
        }
502

    
503
        /**
504
         * Devuelve el FilterPanel asociado al FilterListener
505
         * @return
506
         */
507
        public FilterPanel getFilterPanel() {
508
                return filterPanel;
509
        }
510

    
511
        /**
512
         * Acciones que se realizan al finalizar de crear los recortes de imagen.
513
         * Este m?todo es llamado por el thread TailRasterProcess al finalizar.
514
         */
515
        public void loadLayerInToc(String fileName) {
516
                if (!getFilterPanel().getRadioNewLayer().isSelected())
517
                        return;
518
                if(!new File(fileName).exists())
519
                        return;
520
                try {
521
                        RasterToolsUtil.loadLayer(getFilterPanel().getViewName(), fileName, null);
522
                } catch (RasterNotLoadException e) {
523
                        RasterToolsUtil.messageBoxError("error_cargar_capa", this, e);
524
                }
525
                
526
                RasterModule.layerCount++;
527
                if(filterPanel != null)
528
                        filterPanel.setNewLayerText();
529
        }
530

    
531
        /*
532
         * (non-Javadoc)
533
         * @see org.gvsig.raster.grid.filter.FilterUIListener#actionValuesCompleted(java.util.EventObject)
534
         */
535
        public void actionValuesCompleted(EventObject e) {
536
                actionChangeProperties(e);
537
        }
538
}
539

    
540
/**
541
 * @author Nacho Brodin <brodin_ign@gva.es>
542
 * Filtro para el selector de formatos de escritura
543
 */
544
class WriterFilter extends javax.swing.filechooser.FileFilter {
545
        private String                                filter;
546

    
547
        public WriterFilter(String fil) {
548
                this.filter = fil;
549
        }
550

    
551
        public boolean accept(File f) {
552
                return f.isDirectory() || f.getName().toLowerCase().endsWith("." + filter);
553
        }
554

    
555
        public String getDescription() {
556
                return "." + filter;
557
        }
558
}