Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.plugin / org.gvsig.raster.app / org.gvsig.raster.app.mainplugin / src / main / java / org / gvsig / raster / app / mainplugin / colortable / ColorTablePagePanelController.java @ 43876

History | View | Annotate | Download (17.5 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2017 gvSIG Association
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., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.raster.app.mainplugin.colortable;
24

    
25
import java.awt.Component;
26
import java.awt.event.ComponentAdapter;
27
import java.awt.event.ComponentEvent;
28
import java.awt.event.ItemEvent;
29
import java.awt.event.ItemListener;
30
import java.io.File;
31
import java.util.List;
32
import java.util.Locale;
33

    
34
import javax.swing.DefaultComboBoxModel;
35
import javax.swing.JComponent;
36
import javax.swing.JLabel;
37
import javax.swing.JList;
38
import javax.swing.JSplitPane;
39
import javax.swing.ListCellRenderer;
40
import javax.swing.SwingUtilities;
41
import javax.swing.event.ListSelectionEvent;
42
import javax.swing.event.ListSelectionListener;
43
import javax.swing.event.TableModelEvent;
44
import javax.swing.event.TableModelListener;
45

    
46
import org.apache.commons.lang3.tuple.Pair;
47
import org.slf4j.Logger;
48
import org.slf4j.LoggerFactory;
49

    
50
import org.gvsig.andami.PluginServices;
51
import org.gvsig.andami.PluginsLocator;
52
import org.gvsig.fmap.dal.exception.DataException;
53
import org.gvsig.fmap.dal.raster.BandDescriptor;
54
import org.gvsig.fmap.dal.raster.RasterSet;
55
import org.gvsig.fmap.dal.raster.RasterStore;
56
import org.gvsig.fmap.mapcontext.layers.FLayer;
57
import org.gvsig.fmap.mapcontext.raster.api.RasterLayer;
58
import org.gvsig.fmap.mapcontext.raster.swing.MapContextRasterSwingLocator;
59
import org.gvsig.fmap.mapcontext.raster.swing.previewer.OneLayerPreviewer;
60
import org.gvsig.raster.lib.buffer.api.statistics.Statistics;
61
import org.gvsig.raster.lib.legend.api.RasterLegend;
62
import org.gvsig.raster.lib.legend.api.RasterLegendLocator;
63
import org.gvsig.raster.lib.legend.api.colorinterpretation.ColorInterpretation;
64
import org.gvsig.raster.lib.legend.api.colortable.ColorTable;
65
import org.gvsig.raster.lib.legend.api.colortable.colortableclass.ColorTableClass;
66
import org.gvsig.raster.swing.legend.RasterSwingLegendLocator;
67
import org.gvsig.raster.swing.legend.colortable.editor.ColorTableEditorPanel;
68
import org.gvsig.raster.swing.legend.colortable.selector.ColorTableSelectorPanel;
69
import org.gvsig.tools.ToolsLocator;
70
import org.gvsig.tools.dispose.DisposeUtils;
71
import org.gvsig.tools.dynobject.DynObject;
72
import org.gvsig.tools.i18n.I18nManager;
73

    
74

    
75
/**
76
 * @author fdiaz
77
 *
78
 */
79
public class ColorTablePagePanelController extends ColorTablePagePanelView implements ColorTablePagePanel {
80

    
81
    /**
82
     *
83
     */
84
    private static final long serialVersionUID = 798930218545360652L;
85
    private static final Logger LOG = LoggerFactory.getLogger(ColorTablePagePanelController.class);
86

    
87
    private ColorTableSelectorPanel selector;
88
    private ColorTableEditorPanel editor;
89
    private ColorTable colorTable;
90
    private JSplitPane splPanelRight = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
91
    private RasterLayer rasterLayer;
92
    private OneLayerPreviewer previewer;
93
    private boolean initialized;
94
    private TableModelListener editorTableModelListener;
95
    private RasterLayer clonedLayerForPreview;
96
    private boolean isChanged;
97

    
98
    /**
99
     *
100
     */
101
    public ColorTablePagePanelController() {
102
        this.initialized = false;
103
        DisposeUtils.bind(this);
104
        initializeComponents();
105
        translate();
106
    }
107

    
108
    private void initializeComponents() {
109
        selector = RasterSwingLegendLocator.getSwingManager().createColorTableSelectorPanel();
110
        PluginServices rasterPlugin = PluginsLocator.getManager().getPlugin("org.gvsig.raster.app.mainplugin");
111
        DynObject properties = rasterPlugin.getPluginProperties();
112
        File defaultColorTableLibraryPath = (File) properties.getDynValue("defaultColorTableLibraryPath");
113
        List<Pair<File, ColorTable>> colorTables = RasterLegendLocator.getRasterLegendManager().getColorTables(defaultColorTableLibraryPath);
114
        selector.set(colorTables);
115
        selector.setEditable(false);
116

    
117
        splPanelRight.setTopComponent(getPreviewer().asJComponent());
118
        splPanelRight.setBottomComponent(selector.asJComponent());
119

    
120
        splPanel.setRightComponent(splPanelRight);
121

    
122
        editor = RasterSwingLegendLocator.getSwingManager().createColorTableEditorPanel();
123
        splPanel.setLeftComponent(editor.asJComponent());
124

    
125
        editor.addChkInterpolatedItemListener(new ItemListener() {
126

    
127
            @Override
128
            public void itemStateChanged(ItemEvent e) {
129
                Thread thread = new Thread(new Runnable() {
130
                    @Override
131
                    public void run() {
132
                        SwingUtilities.invokeLater(new Runnable() {
133
                            @Override
134
                            public void run() {
135
                                updatePreviewer();
136
                            }
137
                        });
138
                    }
139
                }, "Check por interpolate changed");
140

    
141
                thread.setDaemon(false);
142
                thread.start();
143
            }
144
        });
145

    
146
        selector.addListSelectionListener(new ListSelectionListener() {
147

    
148
            @Override
149
            public void valueChanged(ListSelectionEvent e) {
150
                Thread thread = new Thread(new Runnable() {
151
                    @Override
152
                    public void run() {
153
                        SwingUtilities.invokeLater(new Runnable() {
154
                            @Override
155
                            public void run() {
156
                                updateColorTable();
157
                            }
158
                        });
159
                    }
160
                }, "Selector changed");
161

    
162
                thread.setDaemon(false);
163
                thread.start();
164
            }
165
        });
166
        splPanel.setDividerLocation(0.75);
167

    
168
        cmbBand.setRenderer(new ComboBandsCellRenderer());
169
        cmbBand.addItemListener(new ItemListener() {
170

    
171
            @Override
172
            public void itemStateChanged(ItemEvent e) {
173
                if(e.getStateChange()==ItemEvent.SELECTED){
174
                    Thread thread = new Thread(new Runnable() {
175
                        @Override
176
                        public void run() {
177
                            SwingUtilities.invokeLater(new Runnable() {
178
                                @Override
179
                                public void run() {
180
                                    updateColorTable();
181
                                }
182
                            });
183
                        }
184
                    }, "Palette band changed");
185

    
186
                    thread.setDaemon(false);
187
                    thread.start();
188
                }
189
            }
190
        });
191
    }
192

    
193
    private void translate() {
194
        I18nManager i18nManager = ToolsLocator.getI18nManager();
195
        lblBand.setText(i18nManager.getTranslation(lblBand.getText()));
196
        lblBand.setToolTipText(i18nManager.getTranslation(lblBand.getToolTipText()));
197
        cmbBand.setToolTipText(i18nManager.getTranslation(cmbBand.getToolTipText()));
198
    }
199

    
200
    /**
201
     * @param locale
202
     *
203
     */
204
    public void setLocate(Locale locale) {
205
        Locale l = super.getLocale();
206
        if (!l.equals(locale)) {
207
            translate();
208
        }
209
        super.setLocale(locale);
210
    }
211

    
212

    
213
    @Override
214
    public JComponent asJComponent() {
215
        return this;
216
    }
217

    
218
    private OneLayerPreviewer getPreviewer() {
219
        if(previewer == null){
220
            previewer = MapContextRasterSwingLocator.getSwingManager().createOneLayerPreviewer();
221
        }
222
        return this.previewer;
223

    
224
    }
225

    
226
    private void initializePreviewer(){
227

    
228
        getPreviewer().setLayer(this.clonedLayerForPreview);
229

    
230
        splPanelRight.setTopComponent(previewer.asJComponent());
231
    }
232

    
233
    /**
234
     *
235
     */
236
    private void updateColorTable() {
237
        if (this.initialized) {
238
            ColorTable selectedColorTable = selector.getSelected();
239
            if (selectedColorTable != null) {
240
                colorTable = selectedColorTable;
241
            } else {
242
                if (colorTable == null) {
243
                    selector.select(0);
244
                    selectedColorTable = selector.getSelected();
245
                    colorTable = selectedColorTable;
246
                }
247
            }
248
            if (((BandItem) cmbBand.getSelectedItem()).getIndex() > -1 && selectedColorTable != null) {
249
                colorTable = adaptToTheBand(selectedColorTable);
250
                setEditorColorTable();
251
            }
252
            updatePreviewer();
253
        }
254
    }
255

    
256
    private void updatePreviewer() {
257
        if (this.initialized) {
258

    
259
            RasterLegend legend = getClonedLayerForPreview().getLegend();
260

    
261
            ColorInterpretation colorInterpretation = legend.getColorInterpretation();
262
            updateColorInterpretation(colorInterpretation);
263

    
264
            isChanged = true;
265
        }
266
    }
267

    
268
    protected ColorTable adaptToTheBand(ColorTable colorTable) {
269
        ColorTable cloned = RasterLegendLocator.getRasterLegendManager().createColorTable();
270
        cloned.copyFrom(colorTable);
271

    
272
        List<ColorTableClass> classes = cloned.getClasses();
273
        double minClassValue = Double.POSITIVE_INFINITY;
274
        double maxClassValue = Double.NEGATIVE_INFINITY;
275
        for (ColorTableClass colorTableClass : classes) {
276
            double value = colorTableClass.getValue();
277
            if(value < minClassValue){
278
                minClassValue = value;
279
            }
280
            if(value > maxClassValue){
281
                maxClassValue = value;
282
            }
283
        }
284

    
285
        Statistics statistics = this.rasterLayer.getStatistics(null);
286

    
287
        int bandIndex = ((BandItem)cmbBand.getSelectedItem()).getIndex();
288
        double minBandValue = statistics.getMin()[bandIndex];
289
        double maxBandValue = statistics.getMax()[bandIndex];
290

    
291
        double ratio = (maxBandValue-minBandValue)/(maxClassValue-minClassValue);
292

    
293
        for (ColorTableClass colorTableClass : classes) {
294
            double value = colorTableClass.getValue();
295
            double adaptedValue = ((value-minClassValue)*ratio)+minBandValue;
296
            colorTableClass.setValue(adaptedValue);
297
        }
298

    
299
        return cloned;
300
    }
301

    
302
    @Override
303
    public boolean fetch(FLayer layer) {
304
        if(isChanged){
305
            RasterLayer rasterLayer = (RasterLayer) layer;
306
            RasterLegend rasterLegend = (RasterLegend) rasterLayer.getLegend();
307
            ColorInterpretation colorInterpretation = rasterLegend.getColorInterpretation();
308
            updateColorInterpretation(colorInterpretation);
309
            updateCmbBands(rasterLayer);
310
        }
311
        return true;
312
    }
313

    
314
    /**
315
     * @param colorInterpretation
316
     */
317
    private void updateColorInterpretation(ColorInterpretation colorInterpretation) {
318
        int paletteBand = ((BandItem)cmbBand.getSelectedItem()).getIndex();
319
        colorInterpretation.setPaletteBand(paletteBand);
320
        ColorTable colorTable2 = this.editor.getColorTable();
321
        if(colorTable2!=null){
322
            try {
323
                colorInterpretation.setPalette((ColorTable)colorTable2.clone());
324
            } catch (CloneNotSupportedException e) {
325
                String message = "Can't clone ColorTable.";
326
                LOG.warn(message, e);
327
                throw new RuntimeException(message, e);
328
            }
329
        }
330
    }
331

    
332
    @Override
333
    public void set(FLayer layer) {
334
        if(this.rasterLayer != null) {
335
            DisposeUtils.dispose(this.rasterLayer);
336
        }
337
        this.rasterLayer = (RasterLayer) layer;
338
        DisposeUtils.bind(this.rasterLayer);
339

    
340
        init();
341
    }
342

    
343
    /**
344
    *
345
    */
346
   private void init() {
347
       updateCmbBands(getClonedLayerForPreview());
348
       RasterLegend legend = null;
349
       legend = getClonedLayerForPreview().getLegend();
350

    
351
       ColorInterpretation colorInterpretation = legend.getColorInterpretation();
352

    
353
       if (colorInterpretation.isPalette()) {
354
           splPanel.getLeftComponent().setEnabled(true);
355
           colorTable = colorInterpretation.getPalette();
356
       } else {
357
           splPanel.getLeftComponent().setEnabled(false);
358
       }
359
       setEditorColorTable();
360

    
361
       isChanged = false;
362
       initializePreviewer();
363
       initialized = true;
364

    
365
   }
366

    
367
    private RasterLayer getClonedLayerForPreview() {
368
        if(this.clonedLayerForPreview==null){
369
            try {
370
                this.clonedLayerForPreview = (RasterLayer) this.rasterLayer.cloneLayer();
371
            } catch (Exception e1) {
372
                LOG.warn("Can't clone the raster layer to preview.", e1);
373
            }
374
        }
375
        return this.clonedLayerForPreview;
376
    }
377

    
378

    
379
    /**
380
     * @return
381
     */
382
    private TableModelListener getEditorTableModelListener() {
383
        if (editorTableModelListener == null) {
384
            editorTableModelListener = new TableModelListener() {
385

    
386
                @Override
387
                public void tableChanged(TableModelEvent e) {
388
                    updatePreviewer();
389
                }
390
            };
391
        }
392
        return editorTableModelListener;
393
    }
394

    
395
    private void updateCmbBands(RasterLayer layer){
396
        RasterStore store = layer.getRasterStore();
397

    
398
        DefaultComboBoxModel<BandItem> currentBandsModel = (DefaultComboBoxModel<BandItem>) cmbBand.getModel();
399
        DefaultComboBoxModel<BandItem> bandsModel = new DefaultComboBoxModel<BandItem>();
400

    
401
        boolean equals = true;
402
        for (int i = -1; i < store.getBands(); i++) {
403
            BandDescriptor bandDescriptor = null;
404
            if(i>=0){
405
                bandDescriptor = store.getBandDescriptor(i);
406
                if(currentBandsModel==null || currentBandsModel.getSize()<=i+1 || currentBandsModel.getElementAt(i+1) == null ||!bandDescriptor.equals(currentBandsModel.getElementAt(i+1).getDescriptor())){
407
                    equals = false;
408
                }
409
            }
410

    
411
            bandsModel.addElement(new BandItem(i,bandDescriptor));
412
        }
413
        if (!equals) {
414
            cmbBand.setModel(bandsModel);
415

    
416
            ColorInterpretation colorInterpretation = layer.getLegend().getColorInterpretation();
417
            if (colorInterpretation.isPalette()) {
418
                cmbBand.setSelectedIndex(colorInterpretation.getPaletteBand() + 1);
419
            } else {
420
                cmbBand.setSelectedIndex(0);
421
            }
422
        }
423
    }
424

    
425
    private static class BandItem{
426

    
427
        private int index;
428
        private BandDescriptor descriptor;
429

    
430
        public BandItem(int index, BandDescriptor descriptor) {
431
            this.setIndex(index);
432
            this.setDescriptor(descriptor);
433
        }
434

    
435
        /**
436
         * @return the index
437
         */
438
        public int getIndex() {
439
            return index;
440
        }
441

    
442
        /**
443
         * @param index the index to set
444
         */
445
        public void setIndex(int index) {
446
            this.index = index;
447
        }
448

    
449
        /**
450
         * @return the descriptor
451
         */
452
        public BandDescriptor getDescriptor() {
453
            return descriptor;
454
        }
455

    
456
        /**
457
         * @param descriptor the descriptor to set
458
         */
459
        public void setDescriptor(BandDescriptor descriptor) {
460
            this.descriptor = descriptor;
461
        }
462
    }
463

    
464
    private static class ComboBandsCellRenderer extends javax.swing.JLabel implements ListCellRenderer<BandItem> {
465

    
466
        /**
467
         *
468
         */
469
        private static final long serialVersionUID = 7763209775607437499L;
470

    
471
        @Override
472
        public Component getListCellRendererComponent(JList<? extends BandItem> list, BandItem value, int index,
473
            boolean isSelected, boolean cellHasFocus) {
474
            I18nManager i18nManager = ToolsLocator.getI18nManager();
475
            if (value == null || value.getIndex() < 0) {
476
                setHorizontalAlignment(JLabel.CENTER);
477
                setText("\u2015");
478
            } else {
479
                setHorizontalAlignment(JLabel.LEFT);
480
                setText(i18nManager.getTranslation("_band") + ": " + (value.getIndex()) + " - '"
481
                    + value.getDescriptor().getName() + "'");
482
            }
483
            return this;
484
        }
485
    }
486

    
487
    @Override
488
    public void setVisible(boolean aFlag) {
489
        super.setVisible(aFlag);
490
        splPanel.setDividerLocation(0.60);
491
        splPanelRight.setDividerLocation(0.40);
492
    }
493

    
494
    /**
495
     *
496
     */
497
    private void setEditorColorTable() {
498
        if (colorTable != null) {
499
            if(editor.getColorTable()!=null){
500
                editor.removeTableModelListener(getEditorTableModelListener());
501
            }
502
            editor.set(colorTable);
503
            if (editorTableModelListener == null) {
504
                editor.addTableModelListener(getEditorTableModelListener());
505
            }
506
        }
507
    }
508

    
509
    @Override
510
    public void dispose() {
511
        if(initialized) {
512
            if(!ToolsLocator.getDisposableManager().release(this)){
513
                return;
514
            }
515
            DisposeUtils.dispose(this.rasterLayer);
516
            this.rasterLayer = null;
517
            DisposeUtils.dispose(this.previewer);
518
            this.previewer = null;
519
            DisposeUtils.disposeQuietly(this.clonedLayerForPreview);
520
            this.clonedLayerForPreview = null;
521
        }
522
    }
523

    
524
}