Statistics
| Revision:

svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / app / extension / reportfromlayout / ConfigureReportFromLayout.java @ 1601

History | View | Annotate | Download (22.2 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.app.extension.reportfromlayout;
7

    
8
import java.awt.Color;
9
import java.awt.Dimension;
10
import java.awt.event.ActionEvent;
11
import java.awt.event.ActionListener;
12
import java.io.ByteArrayOutputStream;
13
import java.io.InputStream;
14
import java.nio.charset.StandardCharsets;
15
import java.util.List;
16
import java.util.function.Predicate;
17
import javax.json.JsonObject;
18
import javax.swing.DefaultComboBoxModel;
19
import javax.swing.JComponent;
20
import javax.swing.JOptionPane;
21
import javax.swing.SwingUtilities;
22
import javax.swing.event.DocumentEvent;
23
import javax.swing.event.DocumentListener;
24
import javax.swing.event.TreeSelectionEvent;
25
import org.apache.commons.codec.binary.Hex;
26
import org.apache.commons.io.IOUtils;
27
import org.apache.commons.lang3.StringUtils;
28
import org.gvsig.andami.PluginServices;
29
import org.gvsig.app.ApplicationLocator;
30
import org.gvsig.app.gui.styling.SymbolSelector;
31
import org.gvsig.app.project.documents.Document;
32
import org.gvsig.app.project.documents.layout.LayoutDocument;
33
import org.gvsig.app.project.documents.layout.fframes.FFrameView;
34
import org.gvsig.app.project.documents.layout.fframes.IFFrame;
35
import org.gvsig.app.project.documents.layout.report.LayoutReportAction;
36
import org.gvsig.app.project.documents.layout.report.LayoutReportActionFactory;
37
import org.gvsig.app.project.documents.layout.report.LayoutReportActionImpl;
38
import org.gvsig.app.project.documents.view.legend.gui.ISymbolSelector;
39
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.dal.swing.DALSwingLocator;
42
import org.gvsig.fmap.dal.swing.DataSwingManager;
43
import org.gvsig.fmap.dal.swing.report.ReportAction;
44
import org.gvsig.fmap.dal.swing.storesrepository.StoresRepositoryController;
45
import org.gvsig.fmap.mapcontext.MapContextLocator;
46
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
47
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
48
import org.gvsig.json.Json;
49
import org.gvsig.json.JsonObjectBuilder;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.dispose.DisposeUtils;
52
import org.gvsig.tools.i18n.I18nManager;
53
import org.gvsig.tools.persistence.PersistenceManager;
54
import org.gvsig.tools.persistence.PersistentState;
55
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
56
import org.gvsig.tools.swing.api.ListElement;
57
import org.gvsig.tools.swing.api.ToolsSwingLocator;
58
import org.gvsig.tools.swing.api.ToolsSwingManager;
59
import org.gvsig.tools.swing.api.ToolsSwingUtils;
60
import org.gvsig.tools.swing.api.documentfilters.PositiveDoubleDocumentFilter;
61
import org.gvsig.tools.swing.api.pickercontroller.ColorPickerController;
62
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
63
import org.gvsig.tools.swing.api.windowmanager.Dialog;
64
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
65
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
66
import org.gvsig.tools.util.LabeledValue;
67
import org.gvsig.tools.util.LabeledValueImpl;
68
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
70

    
71
/**
72
 *
73
 * @author fdiaz
74
 */
75
public class ConfigureReportFromLayout extends ConfigureReportFromLayoutPanelView {
76

    
77
    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigureReportFromLayout.class);
78

    
79
    private StoresRepositoryController treeSourceController;
80
    private FeatureStore source;
81
    private Dialog dialog;
82
    private ISymbol highlightSymbol;
83

    
84
    public ConfigureReportFromLayout() {
85
        this.initComponents();
86

    
87
    }
88
    
89
    private void initComponents() {
90

    
91
        DataSwingManager dataSwingManager = DALSwingLocator.getSwingManager();
92
        translate();
93

    
94
        fillCboLayout();
95
        
96
        this.cboLayout.addActionListener(new ActionListener() {
97
            @Override
98
            public void actionPerformed(ActionEvent e) {
99
                doChangeLayout();
100
            }
101
        });
102
        
103
        this.treeSourceController = dataSwingManager.createStoresRepositoryController(this.treeSource);
104
        this.treeSource.addTreeSelectionListener((TreeSelectionEvent e) -> {
105
            doChangeSource();
106
            doUpdateComponents();
107
        });
108
        
109
        this.cboReport.addActionListener((ActionEvent e) -> {
110
            doChangeReport();
111
        });
112
        
113
        this.txtIdentifier.getDocument().addDocumentListener(new DocumentListener() {
114
            @Override
115
            public void insertUpdate(DocumentEvent e) {
116
                doUpdateComponents();
117
            }
118

    
119
            @Override
120
            public void removeUpdate(DocumentEvent e) {
121
                doUpdateComponents();
122
            }
123

    
124
            @Override
125
            public void changedUpdate(DocumentEvent e) {
126
               doUpdateComponents();
127
            }
128
        });
129
        
130
        this.chkZoomToCurrentRow.addActionListener((ActionEvent e) -> {
131
            doUpdateComponents();
132
        });
133
        
134
        this.btnSelectSymbol.addActionListener((ActionEvent e) -> {
135
            doSelectSymbol();
136
        });
137
        
138
        ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
139
        
140
        PositiveDoubleDocumentFilter.install(txtBufferSize);
141
        
142
        Dimension screensize = ApplicationLocator.getApplicationManager().getUIManager().getInternalSize();
143
        ToolsSwingUtils.ensureHeightWitdh(
144
                this, 
145
                Math.max(3*(screensize.height/4), ToolsSwingUtils.rows2px(80)),
146
                Math.max(2*(screensize.width/4), ToolsSwingUtils.cols2px(35)), 
147
                7*(screensize.height/8), 
148
                3*(screensize.width/4)
149
        );        
150

    
151
        SwingUtilities.invokeLater(this::doUpdateComponents);
152

    
153
    }
154

    
155
    private void doChangeSource() {
156
        FeatureStore theSource = this.treeSourceController.getSelectedFeatureStore();
157
        if( theSource==null ) {
158
            return;
159
        }
160
        if(this.source != null){
161
            DisposeUtils.disposeQuietly(this.source);
162
        }
163
        this.source = theSource;
164
        fillCboReport();
165
        doUpdateComponents();
166
    }
167
    
168
    private void doChangeLayout() {
169
        fillCboView();
170
        doUpdateComponents();
171
    }
172
    
173
    private void doSelectSymbol() {
174

    
175
        if(this.source == null){
176
            return;
177
        }
178
        FeatureAttributeDescriptor geomAttr = this.source.getDefaultFeatureTypeQuietly().getDefaultGeometryAttribute();
179
        if(geomAttr == null){
180
            return;
181
        }
182
        int geomType = geomAttr.getGeomType().getType();
183

    
184
        if(this.highlightSymbol == null) {
185
            this.highlightSymbol = MapContextLocator.getMapContextManager().createSymbol(geomType);
186
        }
187
        ISymbolSelector symSel = SymbolSelector.createSymbolSelector(this.highlightSymbol, geomType);
188

    
189
        WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
190
        windowManager.showWindow((JComponent)symSel, "_Symbol", WindowManager.MODE.DIALOG);
191
        this.highlightSymbol = (ISymbol) symSel.getSelectedObject();
192

    
193
    }
194
    
195

    
196
    private void doUpdateComponents() {
197
        this.treeSourceController.setEnabled(true);
198

    
199
        this.cboReport.setEnabled(this.source != null);
200
        
201
        this.txtBufferSize.setEnabled(this.chkZoomToCurrentRow.isSelected());
202
        
203
        if(this.dialog != null){
204
            boolean enabled = (this.source != null) && (this.getLayoutDocument() != null) && StringUtils.isNotBlank(this.txtIdentifier.getText());
205
            this.dialog.setButtonEnabled(WindowManager_v2.BUTTON_OK, enabled);
206
        }
207
    }
208
    
209
    private void fillCboReport() {
210
        DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
211
        DefaultComboBoxModel<LabeledValue<ReportAction>> model = new DefaultComboBoxModel();
212
        if(this.source == null) {
213
            this.cboReport.setModel(model);
214
            return;
215
        }
216
        List<ReportAction> reports = dataSwingManager.getReportActions(source, (Predicate<JsonObject>) (JsonObject t) -> LayoutReportActionFactory.isJsonApplicable(t));
217
        
218
        model.addElement(new LabeledValueImpl<>("", null));
219
        for (ReportAction report : reports) {
220
            model.addElement(new LabeledValueImpl<>(report.getReportLabel(), report));
221
        }
222
        cboReport.setModel(model);
223

    
224
    }
225
  
226
    List<Document> getLayouts() {
227

    
228
        List<Document> layouts = ApplicationLocator.getProjectManager().getCurrentProject().getDocuments(LayoutDocument.class);
229

    
230
        return layouts;
231

    
232
    }
233

    
234

    
235
    
236
    private void fillCboLayout() {
237
        DefaultComboBoxModel<LabeledValue<LayoutDocument>> model = new DefaultComboBoxModel();
238
        List<Document> layouts = getLayouts();
239
        
240
        for (Document layout : layouts) {
241
            if(layout instanceof LayoutDocument){
242
                model.addElement(new LabeledValueImpl<>(layout.getName(), (LayoutDocument)layout));
243
            }
244
        }
245
        cboLayout.setModel(model);
246
        fillCboView();
247

    
248
    }
249
    
250
    private void fillCboView() {
251
        LayoutDocument layout = getLayoutDocument();
252
        DefaultComboBoxModel<LabeledValue<String>> model = new DefaultComboBoxModel();
253
        if (layout != null) {
254
            int n = 1;
255
            for (IFFrame frame : layout.getLayoutContext().getAllFFrames()) {
256
                if (frame instanceof FFrameView) {
257
                    String tag = frame.getTag();
258
                    if(StringUtils.startsWith(tag, "#") && !StringUtils.equals(tag, "#"+n)){
259
                        model.addElement(new LabeledValueImpl<>(tag+" (invalid tag)",tag));
260
                    } else {
261
                        if(StringUtils.isBlank(tag)){
262
                            tag = "#"+n;
263
                        }
264
                        model.addElement(new LabeledValueImpl<>(tag,tag));
265
                    }
266
                    n++;
267
                }
268
            }
269
        }
270
        this.cboView.setModel(model);
271
    }
272
    
273
    private LayoutReportAction getReportAction(){
274
        LabeledValue<LayoutReportAction> selected = (LabeledValue<LayoutReportAction>)cboReport.getSelectedItem();
275
        if(selected == null){
276
            return null;
277
        }
278
        return selected.getValue();
279
    }
280
    
281
    private LayoutDocument getLayoutDocument(){
282
        LabeledValue<LayoutDocument> selected = (LabeledValue<LayoutDocument>)cboLayout.getSelectedItem();
283
        if(selected == null){
284
            return null;
285
        }
286
        return selected.getValue();
287
    }
288
    
289
    private String getViewTag(){
290
        LabeledValue<String> selected = (LabeledValue<String>)cboView.getSelectedItem();
291
        if(selected == null){
292
            return null;
293
        }
294
        return selected.getValue();
295
    }
296
    
297
    public void fetch(ConfigureReportFromLayoutParameters params){
298
        params.setLayout(this.getLayoutDocument());
299
        params.setSource(this.source);
300
        params.setIdentifier(this.txtIdentifier.getText());
301
        params.setLabel(this.txtLabel.getText());
302
        
303
        params.setCenterToCurrentRow(this.chkCenterToCurrentRow.isSelected());
304
        params.setZoomToCurrentRow(this.chkZoomToCurrentRow.isSelected());
305
        double bufferSize = PositiveDoubleDocumentFilter.getValue(this.txtBufferSize);
306
        params.setBufferSize(bufferSize);
307
//        params.setSelectCurrentRow(this.chkSelectCurrentRow.isSelected());
308
        params.setViewTag(this.getViewTag());
309
        params.setUseIntervalPdfViewer(this.chkUseInternalPdfViewer.isSelected());
310
        params.setHighlightRecord(this.chkHighlightRecord.isSelected());
311
        params.setHighlightSymbol(this.highlightSymbol);
312
    }
313

    
314
    private void translate() {
315
        ToolsSwingManager manager = ToolsSwingLocator.getToolsSwingManager();
316
        manager.translate(lblLayout);
317
        manager.translate(lblSource);
318
        manager.translate(lblReport);
319
        manager.translate(lblIdentifier);
320
        manager.translate(lblLabel);
321
        manager.translate(lblViewSeparator);
322
        manager.translate(lblView);
323
        manager.translate(chkCenterToCurrentRow);
324
        manager.translate(chkZoomToCurrentRow);
325
        manager.translate(lblBufferSize);
326
//        manager.translate(chkSelectCurrentRow);
327
        manager.translate(chkUseInternalPdfViewer);
328
        manager.translate(txtBufferSize);
329
        manager.translate(chkHighlightRecord);
330
    }
331
    
332
    public boolean doConfigureReportFromLayout(ConfigureReportFromLayoutParameters params) {
333
        LayoutDocument layout = params.getLayout();
334
        FeatureStore source = params.getSource();
335
        String identifier = params.getIdentifier();
336
        String label = params.getLabel();
337
        
338
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
339
        I18nManager i18n = ToolsLocator.getI18nManager();
340
        
341
        if(layout == null){
342
            dialogs.messageDialog(
343
                    i18n.getTranslation("_Layout_cant_be_null"), 
344
                    null,
345
                    "_Configure_report_from_layout", 
346
                    JOptionPane.WARNING_MESSAGE);
347
            return false;
348
        }
349

    
350
        if(source == null){
351
            dialogs.messageDialog(
352
                    i18n.getTranslation("_Source_cant_be_null"), 
353
                    null,
354
                    "_Configure_report_from_layout", 
355
                    JOptionPane.WARNING_MESSAGE);
356
            return false;
357
        }
358

    
359
        if(StringUtils.isBlank(identifier)){
360
            dialogs.messageDialog(
361
                    i18n.getTranslation("_Identifier_cant_be_null"), 
362
                    null,
363
                    "_Configure_report_from_layout", 
364
                    JOptionPane.WARNING_MESSAGE);
365
            return false;
366
        }
367
        
368
        Color fillColor = params.getFillColor();
369
        Color lineColor = params.getLineColor();
370
        boolean centerToCurrentRow = params.isCenterToCurrentRow();
371
        boolean zoomToCurrentRow = params.isZoomToCurrentRow();
372
        double bufferSize = params.getBufferSize();
373
        boolean highlightRecord = params.isHighlightRecord();
374
        ISymbol highlightSymbol = params.getHighlightSymbol();
375
        boolean useInternalPdfViewer = params.isUseIntervalPdfViewer();
376
        String viewTag = params.getViewTag();
377
                
378
        return doConfigureReportFromLayout(
379
                source, 
380
                layout, 
381
                identifier, 
382
                label, 
383
                lineColor,
384
                fillColor,
385
                centerToCurrentRow, 
386
                zoomToCurrentRow, 
387
                bufferSize, 
388
                highlightRecord,
389
                highlightSymbol,
390
                viewTag,
391
                useInternalPdfViewer);
392
        
393
        
394
    }
395
    
396
    public boolean doConfigureReportFromLayout(
397
            FeatureStore store, 
398
            LayoutDocument layout, 
399
            String name, 
400
            String label,
401
            Color lineColor,
402
            Color fillColor,
403
            boolean centerToCurrentRow,
404
            boolean zoomToCurrentRow,
405
            double bufferSize,
406
            boolean highlightRecord,
407
            ISymbol highlightSymbol,
408
            String viewTag,
409
            boolean useInternalPdfViewer
410
    ) {
411
        ResourcesStorage.Resource resource = null;
412
        ResourcesStorage.Resource resourceLayout = null;
413
        boolean selfContained = layout.isPersistIndependent();
414
        try {
415
            ResourcesStorage resources = store.getResourcesStorage();
416
            
417
            String resourceName = getResourceName(resources, name);
418
            if(resourceName == null){
419
                resourceName = getNextResourceName(resources, "report");
420
            }
421
            
422
            String templateName = LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME;
423
            if(StringUtils.contains(resourceName, resources.getSeparator())){
424
                templateName = StringUtils.replaceIgnoreCase(resourceName, resources.getSeparator()+"report", resources.getSeparator()+LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME);
425
            }
426
            JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
427
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_NAME, name);
428
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_TYPE, LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME);
429
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_LABEL, label);
430
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_TEMPLATE_NAME, templateName);
431
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_HIGHLIGHT_SYMBOL, this.toString(highlightSymbol));
432
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_LINE_COLOR, lineColor.getRGB()&(lineColor.getAlpha()<<24));
433
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_FILL_COLOR, fillColor.getRGB()&(fillColor.getAlpha()<<24));
434
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_CENTER_TO_CURRENT_ROW, centerToCurrentRow);
435
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_ZOOM_TO_CURRENT_ROW, zoomToCurrentRow);
436
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_BUFFER_SIZE, bufferSize);
437
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_HIGHLIGHT_RECORD, highlightRecord);
438
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_VIEW_TAG, viewTag);
439
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_USE_INTERNAL_PDF_VIEWER, useInternalPdfViewer);
440
            
441
            resource = resources.getResource(resourceName);
442
            IOUtils.write(jsonBuilder.toString(), resource.asOutputStream(), StandardCharsets.UTF_8);
443
            
444
            resourceLayout = resources.getResource(templateName);
445
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
446
            layout.setPersistIndependent(true);
447
            PersistentState persistentState = persistenceManager.getState(layout.getMainWindow());
448
            persistenceManager.saveState(persistentState, resourceLayout.asOutputStream());
449
            ((JComponent)dialog).setVisible(false);
450
            return true;
451
        } catch (Exception ex) {
452
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
453
            I18nManager i18n = ToolsLocator.getI18nManager();
454
            dialogs.messageDialog(
455
                    i18n.getTranslation("_Cant_configure_report_from_layout"), 
456
                    null,
457
                    "_Configure_report_from_layout", 
458
                    JOptionPane.WARNING_MESSAGE);
459
            return false;
460
        } finally {
461
            layout.setPersistIndependent(selfContained);
462
            IOUtils.closeQuietly(resource);
463
            IOUtils.closeQuietly(resourceLayout);
464
        }
465
        
466
    }
467
    
468
    private String toString(ISymbol symbol){
469
        try {
470
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
471
            PersistentState state = persistenceManager.getState(symbol);
472
            ByteArrayOutputStream out = new ByteArrayOutputStream();
473
            persistenceManager.saveState(state, out);
474
            return Hex.encodeHexString(out.toByteArray());
475
        } catch (Exception ex) {
476
            throw new RuntimeException("Can't persist symbol", ex);
477
        }
478
    }
479
    
480
    private String getNextResourceName(ResourcesStorage resources, String resourceName){
481
        List<ResourcesStorage.Resource> reports = resources.getResources(resourceName);
482
        if(reports == null || reports.isEmpty()){
483
            return resourceName;
484
        }
485
        int n = -1;
486
        for (ResourcesStorage.Resource report : reports) {
487
            if(StringUtils.contains(report.getName(), resources.getSeparator())){
488
                String[] s = StringUtils.split(report.getName(), resources.getSeparator());
489
                n = Math.max(n, Integer.parseInt(s[0]));
490
            } else {
491
                n=0;
492
            }
493
        }
494
        
495
        if (n < 0) {
496
            return resourceName;
497
        }
498
        
499
        n++;
500
        return String.valueOf(n) + resources.getSeparator() + resourceName;
501

    
502
        
503
    }
504
    
505
    private String getResourceName(ResourcesStorage resources, String reportName) {
506
        try {
507
            if (resources != null) {
508
                List<ResourcesStorage.Resource> reportsResources = resources.getResources("report");
509
                if (reportsResources != null && !reportsResources.isEmpty()) {
510
                    for (ResourcesStorage.Resource resource : reportsResources) {
511
                        InputStream is = null;
512
                        try {
513
                            is = resource.asInputStream();
514
                            JsonObject json = javax.json.Json.createReader(is).readObject();
515
                            String name = json.getString(LayoutReportActionImpl.LAYOUT_REPORT_NAME, null);
516
                            if(StringUtils.equalsIgnoreCase(name, reportName)){
517
                                return resource.getName();
518
                            }
519
                        } catch (Exception ex) {
520
                            LOGGER.warn("Can't load report form resource (" + resource.getURL() + ")", ex);
521
                        } finally {
522
                            IOUtils.closeQuietly(is);
523
                        }
524
                        DisposeUtils.disposeQuietly(resource);
525
                    }
526
                }
527
            }
528
        } finally {
529
            DisposeUtils.disposeQuietly(resources);
530
        }
531
        return null;
532
    }
533
    
534

    
535
    private void doChangeReport() {
536
        LayoutReportAction report = getReportAction();
537
        if(report == null){
538
            this.txtIdentifier.setText("");
539
            this.txtLabel.setText("");
540
        } else {
541
            this.txtIdentifier.setText(report.getReportName());
542
            this.txtLabel.setText(report.getReportLabel());
543
            this.chkCenterToCurrentRow.setSelected(report.isCenterToCurrentRow());
544
            this.chkZoomToCurrentRow.setSelected(report.isZoomToCurrentRow());
545
            PositiveDoubleDocumentFilter.setValue(this.txtBufferSize,report.getBufferSize());
546
            this.chkHighlightRecord.setSelected(report.isHighlightRecord());
547
            ListElement.setSelected(this.cboView, report.getViewTag());
548
            this.chkUseInternalPdfViewer.setSelected(report.isUseInternalPdfViewer());
549
        }
550
        doUpdateComponents();
551
    }
552

    
553
    void setDialog(Dialog dialog) {
554
        this.dialog = dialog;
555
    }
556
    
557

    
558
    
559
}