001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2015
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028package edu.wisc.ssec.mcidasv.control;
029
030import java.awt.Container;
031import java.awt.FlowLayout;
032import java.awt.event.ActionEvent;
033import java.awt.event.ActionListener;
034import java.rmi.RemoteException;
035import java.util.Hashtable;
036import java.util.Iterator;
037
038import javax.swing.Box;
039import javax.swing.JButton;
040import javax.swing.JLabel;
041import javax.swing.JPanel;
042import javax.swing.JTextField;
043
044import org.slf4j.Logger;
045import org.slf4j.LoggerFactory;
046
047import net.miginfocom.swing.MigLayout;
048
049import ucar.unidata.data.DataChoice;
050import ucar.unidata.data.DataSelection;
051import ucar.unidata.idv.control.DisplayControlImpl;
052import ucar.unidata.util.ColorTable;
053import ucar.unidata.util.LogUtil;
054import ucar.visad.display.DisplayMaster;
055
056import visad.BaseColorControl;
057import visad.CoordinateSystem;
058import visad.Data;
059import visad.FieldImpl;
060import visad.FlatField;
061import visad.FunctionType;
062import visad.ScalarMap;
063import visad.ScalarMapControlEvent;
064import visad.ScalarMapEvent;
065import visad.ScalarMapListener;
066import visad.VisADException;
067import visad.georef.MapProjection;
068
069import edu.wisc.ssec.mcidasv.data.hydra.ImageRGBDisplayable;
070
071public class RGBCompositeControl extends DisplayControlImpl {
072
073   private static final Logger logger = LoggerFactory.getLogger(RGBCompositeControl.class);
074        
075   /** Displayable for the data */
076   private ImageRGBDisplayable imageDisplay;
077
078   private DisplayMaster displayMaster;
079
080   private ScalarMap redMap = null;
081   private ScalarMap grnMap = null;
082   private ScalarMap bluMap = null;
083
084   float[][] redTable = null;
085   float[][] grnTable = null;
086   float[][] bluTable = null;
087
088   final private double[] redRange = new double[] {Double.NaN, Double.NaN};
089   final private double[] grnRange = new double[] {Double.NaN, Double.NaN};
090   final private double[] bluRange = new double[] {Double.NaN, Double.NaN};
091
092   final double[] initRedRange = new double[] {Double.NaN, Double.NaN};
093   final double[] initGrnRange = new double[] {Double.NaN, Double.NaN};
094   final double[] initBluRange = new double[] {Double.NaN, Double.NaN};
095
096   private FieldImpl imageField = null;
097   private MapProjection mapProjection = null;
098        
099   private double gamma = 1.0;
100
101   private double redGamma = 1.0;
102   private double grnGamma = 1.0;
103   private double bluGamma = 1.0;
104
105   private final JTextField gammaTxtFld =
106        new JTextField(Float.toString(1f), 4);
107   private final JTextField redGammaTxtFld =
108        new JTextField(Float.toString(1f), 4);
109   private final JTextField grnGammaTxtFld =
110        new JTextField(Float.toString(1f), 4);
111   private final JTextField bluGammaTxtFld =
112        new JTextField(Float.toString(1f), 4);
113
114   private final JTextField redLowTxtFld =
115        new JTextField(Float.toString(1f), 10);
116   private final JTextField redHighTxtFld =
117        new JTextField(Float.toString(1f), 10);
118   private final JTextField grnLowTxtFld =
119        new JTextField(Float.toString(1f), 10);
120   private final JTextField grnHighTxtFld =
121        new JTextField(Float.toString(1f), 10);
122   private final JTextField bluLowTxtFld =
123        new JTextField(Float.toString(1f), 10);
124   private final JTextField bluHighTxtFld =
125        new JTextField(Float.toString(1f), 10);
126   
127   public final static String FORMULA_IN_PROGRESS_FLAG = "Formula_Active";
128
129   public RGBCompositeControl() {
130     super();
131   }
132
133   public boolean init(DataChoice dataChoice) throws VisADException, RemoteException {
134           
135     displayMaster = getViewManager().getMaster();
136     DataSelection dataSelection = getDataSelection();
137     
138     // TJJ Jul 2014
139     // by sharing a property via the active View Manager, we can signal all three 
140     // preview windows they are part of an in-progress RGB Composite. If so, it 
141     // appears we need to use a shared HydraContext so our geographic coverage
142     // subset applies across channels.  
143     
144     Hashtable ht = getIdv().getViewManager().getProperties();
145     ht.put(FORMULA_IN_PROGRESS_FLAG, true);
146     
147     imageField = (FieldImpl) dataChoice.getData(dataSelection);
148
149     imageDisplay = new ImageRGBDisplayable("rgb composite", null, false, imageField);
150     
151     ht.put(FORMULA_IN_PROGRESS_FLAG, false);
152
153     Iterator iter = imageDisplay.getScalarMapSet().iterator();
154     while (iter.hasNext()) {
155         ScalarMap map = (ScalarMap) iter.next();
156         if (map.getScalarName().startsWith("redimage")) {
157                 redMap = map;
158         }
159         if (map.getScalarName().startsWith("greenimage")) {
160                 grnMap = map;
161         }
162         if (map.getScalarName().startsWith("blueimage")) {
163                 bluMap = map;
164         }
165     }
166
167     if (checkRange()) { //- from unpersistence if true, initialize gui, ScalarMaps
168       double[] redRange = getRedRange();
169       double[] grnRange = getGrnRange();
170       double[] bluRange = getBluRange();
171
172       initRedRange[0] = redRange[0];
173       initRedRange[1] = redRange[1];
174       initGrnRange[0] = grnRange[0];
175       initGrnRange[1] = grnRange[1];
176       initBluRange[0] = bluRange[0];
177       initBluRange[1] = bluRange[1];
178
179       redLowTxtFld.setText(Float.toString((float)redRange[0]));
180       redHighTxtFld.setText(Float.toString((float)redRange[1]));
181       grnLowTxtFld.setText(Float.toString((float)grnRange[0]));
182       grnHighTxtFld.setText(Float.toString((float)grnRange[1]));
183       bluLowTxtFld.setText(Float.toString((float)bluRange[0]));
184       bluHighTxtFld.setText(Float.toString((float)bluRange[1]));
185   
186       gammaTxtFld.setText(Float.toString((float)gamma));
187       redGammaTxtFld.setText(Float.toString((float)redGamma));
188       grnGammaTxtFld.setText(Float.toString((float)grnGamma));
189       bluGammaTxtFld.setText(Float.toString((float)bluGamma));
190
191       redMap.setRange(redRange[0], redRange[1]);
192       grnMap.setRange(grnRange[0], grnRange[1]);
193       bluMap.setRange(bluRange[0], bluRange[1]);
194     } 
195     else {
196       redMap.resetAutoScale();
197       grnMap.resetAutoScale();
198       bluMap.resetAutoScale();
199
200       redMap.addScalarMapListener(new ColorMapListener(redMap, initRedRange, redRange, redLowTxtFld, redHighTxtFld));
201       grnMap.addScalarMapListener(new ColorMapListener(grnMap, initGrnRange, grnRange, grnLowTxtFld, grnHighTxtFld));
202       bluMap.addScalarMapListener(new ColorMapListener(bluMap, initBluRange, bluRange, bluLowTxtFld, bluHighTxtFld));
203     }
204
205     setShowInDisplayList(true);
206
207     addDisplayable(imageDisplay, FLAG_COLORTABLE);
208
209     return true;
210   }
211
212   public void initDone() {
213     while (true) {
214         if (null != redMap.getControl()) {
215            redTable = ((BaseColorControl) redMap.getControl()).getTable();
216            break;
217         }
218     }
219     while (true) {
220         if (null != grnMap.getControl()) {
221             grnTable = ((BaseColorControl) grnMap.getControl()).getTable();
222             break;
223         }
224     }
225     while (true) {
226         if (null != bluMap.getControl()) {
227             bluTable = ((BaseColorControl) bluMap.getControl()).getTable();
228             break;
229         }
230     } 
231
232     float[][] newRedTbl = getZeroOutArray(redTable);
233     float[][] newGrnTbl = getZeroOutArray(grnTable);
234     float[][] newBluTbl = getZeroOutArray(bluTable);
235
236     for (int k=0; k<redTable[0].length; k++) {
237       newRedTbl[0][k] = (float) Math.pow(redTable[0][k], redGamma);
238       newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], grnGamma);
239       newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], bluGamma);
240     }
241
242     try {
243       displayMaster.setDisplayInactive();
244       ((BaseColorControl)redMap.getControl()).setTable(newRedTbl);
245       ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl);
246       ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl);
247       imageDisplay.loadData(imageField);
248       displayMaster.setDisplayActive();
249     } catch(Exception ex) {
250       LogUtil.logException("setDisplayInactive", ex);
251     }
252   }
253
254   public MapProjection getDataProjection() {
255     CoordinateSystem cs = null;
256     try {
257       if (imageField instanceof FlatField) {
258         cs = ((FunctionType)imageField.getType()).getDomain().getCoordinateSystem();
259       } 
260       else if (imageField instanceof FieldImpl) {
261         Data dat = imageField.getSample(0, false);
262         if (dat instanceof FlatField) {
263           FlatField img = (FlatField) dat;
264           cs = ((FunctionType)img.getType()).getDomain().getCoordinateSystem();
265         }
266       }
267     }
268     catch (Exception ex) {
269       LogUtil.logException("problem accessing data", ex);
270     }
271
272     if (cs instanceof MapProjection) mapProjection = (MapProjection) cs;
273
274     return mapProjection;
275   }
276
277   boolean checkRange() {
278     if (Double.isNaN(redRange[0]) || Double.isNaN(grnRange[0]) || Double.isNaN(bluRange[0])) {
279       return false;
280     }
281     else {
282       return true;
283     }
284   }
285
286   private void updateRedRange(double lo, double hi) {
287     redRange[0] = lo;
288     redRange[1] = hi;
289     redHighTxtFld.setText(Float.toString((float)hi));
290     redLowTxtFld.setText(Float.toString((float)lo));
291     try {
292       redMap.setRange(lo, hi);
293     } catch (VisADException ex) {
294       LogUtil.logException("redMap.setRange", ex);
295     } catch (RemoteException ex) {
296       LogUtil.logException("redMap.setRange", ex);
297     }
298   }
299
300   public void setRedRange(double[] range) {
301     redRange[0] = range[0];
302     redRange[1] = range[1];
303   }
304
305   public double[] getRedRange() {
306     return new double[] {redRange[0], redRange[1]};
307   }
308
309   private void updateGrnRange(double lo, double hi) {
310     grnRange[0] = lo;
311     grnRange[1] = hi;
312     grnHighTxtFld.setText(Float.toString((float)hi));
313     grnLowTxtFld.setText(Float.toString((float)lo));
314     try {
315       grnMap.setRange(lo, hi);
316     } catch (VisADException ex) {
317       LogUtil.logException("grnMap.setRange", ex);
318     } catch (RemoteException ex) {
319       LogUtil.logException("grnMap.setRange", ex);
320     }
321   }
322
323   public void setGrnRange(double[] range) {
324     grnRange[0] = range[0];
325     grnRange[1] = range[1];
326   }
327
328   public double[] getGrnRange() {
329     return new double[] {grnRange[0], grnRange[1]};
330   }
331
332   private void updateBluRange(double lo, double hi) {
333     bluRange[0] = lo;
334     bluRange[1] = hi;
335     bluHighTxtFld.setText(Float.toString((float)hi));
336     bluLowTxtFld.setText(Float.toString((float)lo));
337     try {
338       bluMap.setRange(lo, hi);
339     } catch (VisADException ex) {
340       LogUtil.logException("bluMap.setRange", ex);
341     } catch (RemoteException ex) {
342       LogUtil.logException("bluMap.setRange", ex);
343     }
344   }
345
346   public void setBluRange(double[] range) {
347     bluRange[0] = range[0];
348     bluRange[1] = range[1];
349   }
350
351   public double[] getBluRange() {
352     return new double[] {bluRange[0], bluRange[1]};
353   }
354
355   public void setRedGamma(double gamma) {
356     redGamma = gamma;
357   }
358
359   public double getRedGamma() {
360     return redGamma;
361   }
362
363   public void setGrnGamma(double gamma) {
364     grnGamma = gamma;
365   }
366
367   public double getGrnGamma() {
368     return grnGamma;
369   }
370
371   public void setBluGamma(double gamma) {
372     bluGamma = gamma;
373   }
374
375   public double getBluGamma() {
376     return bluGamma;
377   }
378
379   public void setGamma(double gamma) {
380     this.gamma = gamma;
381   }
382
383   public double getGamma() {
384     return gamma;
385   }
386
387   private void updateGamma(double gamma) {
388     setGamma(gamma);
389     setRedGamma(gamma);
390     setGrnGamma(gamma);
391     setBluGamma(gamma);
392     redGammaTxtFld.setText(Float.toString((float)gamma));
393     grnGammaTxtFld.setText(Float.toString((float)gamma));
394     bluGammaTxtFld.setText(Float.toString((float)gamma));
395        
396     float[][] newRedTbl = getZeroOutArray(redTable);
397     float[][] newGrnTbl = getZeroOutArray(grnTable);
398     float[][] newBluTbl = getZeroOutArray(bluTable);
399
400     for (int k=0; k<redTable[0].length; k++) {
401       newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma);
402       newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma);
403       newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma);
404     }
405     try {
406       displayMaster.setDisplayInactive();
407       ((BaseColorControl)redMap.getControl()).setTable(newRedTbl);
408       ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl);
409       ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl);
410       displayMaster.setDisplayActive();
411     } catch(Exception ex) {
412       LogUtil.logException("setDisplayInactive", ex);
413     }
414   }
415
416   private void updateRedGamma(double gamma) {
417     setRedGamma(gamma);
418
419     float[][] newRedTbl = getZeroOutArray(redTable);
420
421     for (int k=0; k<redTable[0].length; k++) {
422       newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma);
423     }
424
425     try {
426       displayMaster.setDisplayInactive();
427       ((BaseColorControl)redMap.getControl()).setTable(newRedTbl);
428       displayMaster.setDisplayActive();
429     } catch(Exception ex) {
430       LogUtil.logException("setDisplayInactive", ex);
431     }
432   }
433
434   private void updateGrnGamma(double gamma) {
435     setGrnGamma(gamma);
436
437     float[][] newGrnTbl = getZeroOutArray(grnTable);
438     for (int k=0; k<grnTable[0].length; k++) {
439       newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma);
440     }
441
442     try {
443       displayMaster.setDisplayInactive();
444       ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl);
445       displayMaster.setDisplayActive();
446     } catch(Exception ex) {
447       LogUtil.logException("setDisplayInactive", ex);
448     }
449   }
450
451   private void updateBluGamma(double gamma) {
452     setBluGamma(gamma);
453
454     float[][] newBluTbl = getZeroOutArray(bluTable);
455     for (int k=0; k<bluTable[0].length; k++) {
456       newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma);
457     }
458
459     try {
460       displayMaster.setDisplayInactive();
461       ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl);
462       displayMaster.setDisplayActive();
463     } catch(Exception ex) {
464       LogUtil.logException("setDisplayInactive", ex);
465     }
466   }
467
468   public float[][] getZeroOutArray(float[][] array) {
469     float[][] newArray = new float[array.length][array[0].length];
470     for (int i=0; i<newArray.length; i++) {
471       for (int j=0; j<newArray[0].length; j++) {
472         newArray[i][j] = 0f;
473       }
474     }
475     return newArray;
476   }
477
478   protected ColorTable getInitialColorTable() {
479     return getDisplayConventions().getParamColorTable("image");
480   }
481
482   public Container doMakeContents() {
483
484     JButton allGammaButton = new JButton("Apply to All Gamma Fields");
485     allGammaButton.addActionListener(new ActionListener() {
486         public void actionPerformed(ActionEvent e) {
487             String tmp = gammaTxtFld.getText().trim();
488             updateGamma(Double.valueOf(tmp));
489         }
490     });
491
492      gammaTxtFld.addActionListener(new ActionListener() {
493          public void actionPerformed(ActionEvent e) {
494              String tmp = gammaTxtFld.getText().trim();
495              updateGamma(Double.valueOf(tmp));
496          }
497      });
498   
499     redLowTxtFld.addActionListener(new ActionListener() {
500         public void actionPerformed(ActionEvent e) {
501            String tmp = redLowTxtFld.getText().trim();
502            updateRedRange(Double.valueOf(tmp), redRange[1]);
503         }
504     });
505     
506     redHighTxtFld.addActionListener(new ActionListener() {
507         public void actionPerformed(ActionEvent e) {
508            String tmp = redHighTxtFld.getText().trim();
509            updateRedRange(redRange[0], Double.valueOf(tmp));
510         }
511     });
512
513     redGammaTxtFld.addActionListener(new ActionListener() {
514         public void actionPerformed(ActionEvent e) {
515             String tmp = redGammaTxtFld.getText().trim();
516             updateRedGamma(Double.valueOf(tmp));
517         }
518     });
519
520     JButton redReset = new JButton("Reset");
521     redReset.addActionListener(new ActionListener() {
522       public void actionPerformed(ActionEvent e) {
523         updateRedRange(initRedRange[0], initRedRange[1]);
524         redRange[0] = initRedRange[0];
525         redRange[1] = initRedRange[1];
526         redLowTxtFld.setText(Float.toString((float)redRange[0]));
527         redHighTxtFld.setText(Float.toString((float)redRange[1]));
528         updateRedGamma(1.0);
529         redGammaTxtFld.setText("1.0");
530       }
531     });
532   
533     grnLowTxtFld.addActionListener(new ActionListener() {
534         public void actionPerformed(ActionEvent e) {
535            String tmp = grnLowTxtFld.getText().trim();
536            updateGrnRange(Double.valueOf(tmp), grnRange[1]);
537         }
538     });
539
540     grnHighTxtFld.addActionListener(new ActionListener() {
541         public void actionPerformed(ActionEvent e) {
542            String tmp = grnHighTxtFld.getText().trim();
543            updateGrnRange(grnRange[0], Double.valueOf(tmp));
544         }
545     });
546
547     grnGammaTxtFld.addActionListener(new ActionListener() {
548         public void actionPerformed(ActionEvent e) {
549             String tmp = grnGammaTxtFld.getText().trim();
550             updateGrnGamma(Double.valueOf(tmp));
551         }
552     });
553
554     JButton grnReset = new JButton("Reset");
555     grnReset.addActionListener(new ActionListener() {
556       public void actionPerformed(ActionEvent e) {
557         updateGrnRange(initGrnRange[0], initGrnRange[1]);
558         grnRange[0] = initGrnRange[0];
559         grnRange[1] = initGrnRange[1];
560         grnLowTxtFld.setText(Float.toString((float)grnRange[0]));
561         grnHighTxtFld.setText(Float.toString((float)grnRange[1]));
562         updateGrnGamma(1.0);
563         grnGammaTxtFld.setText("1.0");
564       }
565     });
566   
567     bluLowTxtFld.addActionListener(new ActionListener() {
568         public void actionPerformed(ActionEvent e) {
569            String tmp = bluLowTxtFld.getText().trim();
570            updateBluRange(Double.valueOf(tmp), bluRange[1]);
571         }
572     });
573
574     bluHighTxtFld.addActionListener(new ActionListener() {
575         public void actionPerformed(ActionEvent e) {
576            String tmp = bluHighTxtFld.getText().trim();
577            updateBluRange(bluRange[0], Double.valueOf(tmp));
578         }
579     });
580
581     bluGammaTxtFld.addActionListener(new ActionListener() {
582         public void actionPerformed(ActionEvent e) {
583             String tmp = bluGammaTxtFld.getText().trim();
584             updateBluGamma(Double.valueOf(tmp));
585         }
586     });
587
588     JButton bluReset = new JButton("Reset");
589     bluReset.addActionListener(new ActionListener() {
590       public void actionPerformed(ActionEvent e) {
591         updateBluRange(initBluRange[0], initBluRange[1]);
592         bluRange[0] = initBluRange[0];
593         bluRange[1] = initBluRange[1];
594         bluLowTxtFld.setText(Float.toString((float)bluRange[0]));
595         bluHighTxtFld.setText(Float.toString((float)bluRange[1]));
596         updateBluGamma(1.0);
597         bluGammaTxtFld.setText("1.0");
598       }
599     });
600
601     JButton applyButton = new JButton("Apply");
602     applyButton.addActionListener(new ActionListener() {
603       public void actionPerformed(ActionEvent e) {
604            String redLow = redLowTxtFld.getText().trim();
605            String redHigh = redHighTxtFld.getText().trim();
606            updateRedRange(Double.valueOf(redLow), Double.valueOf(redHigh));
607            String grnLow = grnLowTxtFld.getText().trim();
608            String grnHigh = grnHighTxtFld.getText().trim();
609            updateGrnRange(Double.valueOf(grnLow), Double.valueOf(grnHigh));
610            String bluLow = bluLowTxtFld.getText().trim();
611            String bluHigh = bluHighTxtFld.getText().trim();
612            updateBluRange(Double.valueOf(bluLow), Double.valueOf(bluHigh));
613
614            String tmp = redGammaTxtFld.getText().trim();
615            updateRedGamma(Double.valueOf(tmp));
616            tmp = grnGammaTxtFld.getText().trim();
617            updateGrnGamma(Double.valueOf(tmp));
618            tmp = bluGammaTxtFld.getText().trim();
619            updateBluGamma(Double.valueOf(tmp));
620       }
621     });
622     
623     JPanel topPanel = new JPanel(new MigLayout());
624     topPanel.add(new JLabel("Red range: "));
625     topPanel.add(redLowTxtFld);
626     topPanel.add(redHighTxtFld);
627     topPanel.add(new JLabel("Red Gamma: "));
628     topPanel.add(redGammaTxtFld);
629     topPanel.add(redReset, "wrap");
630     
631     topPanel.add(new JLabel("Green range: "));
632     topPanel.add(grnLowTxtFld);
633     topPanel.add(grnHighTxtFld);
634     topPanel.add(new JLabel("Green Gamma: "));
635     topPanel.add(grnGammaTxtFld);
636     topPanel.add(grnReset, "wrap");
637     
638     topPanel.add(new JLabel("Blue range: "));
639     topPanel.add(bluLowTxtFld);
640     topPanel.add(bluHighTxtFld);
641     topPanel.add(new JLabel("Blue Gamma: "));
642     topPanel.add(bluGammaTxtFld);
643     topPanel.add(bluReset, "wrap");
644     
645     topPanel.add(Box.createHorizontalStrut(1), "span 5");
646     topPanel.add(applyButton, "wrap");
647     
648     JPanel bottomPanel = new JPanel(new MigLayout());
649     bottomPanel.add(new JLabel("Common Gamma: "));
650     bottomPanel.add(gammaTxtFld);
651     bottomPanel.add(allGammaButton);
652     
653     JPanel mainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
654     mainPanel.add(topPanel);
655     mainPanel.add(bottomPanel);
656
657     return mainPanel;
658   }
659
660  private class ColorMapListener implements ScalarMapListener
661  {
662    ScalarMap clrMap;
663
664    double[] range = null;
665    double[] initRange = null;
666
667    JTextField lowTxtFld;
668    JTextField highTxtFld;
669
670    ColorMapListener(ScalarMap clrMap, double[] initRange, double[] range, JTextField lowTxtFld, JTextField highTxtFld) {
671      this.clrMap = clrMap;
672      this.lowTxtFld = lowTxtFld;
673      this.highTxtFld = highTxtFld;
674      this.range = range;
675      this.initRange = initRange;
676    }
677
678
679    public void controlChanged(ScalarMapControlEvent event) throws RemoteException, VisADException {
680    }
681
682    public void mapChanged(ScalarMapEvent event) throws RemoteException, VisADException {       
683      if (event.getId() == ScalarMapEvent.AUTO_SCALE) {
684            double[] rng = clrMap.getRange();
685            boolean shouldRemove = false;
686            //Ghansham: decide whether it is first time. The cleaner way
687            if (!Double.isNaN(rng[0]) && !Double.isNaN(rng[1]) && Double.isNaN(initRange[0]) && Double.isNaN(initRange[1])) {
688                shouldRemove = true;
689            }
690            range[0] = rng[0];
691            range[1] = rng[1];
692            initRange[0] = rng[0];
693            initRange[1] = rng[1];
694            lowTxtFld.setText(Float.toString((float)rng[0]));
695            highTxtFld.setText(Float.toString((float)rng[1]));
696            //Ghansham:If its first time remove the scalarmaplistener and setRange manually to disable autscaling of the scalarmap
697            if(shouldRemove) {
698                clrMap.removeScalarMapListener(this);
699            //-Lock out auto-scaling
700                clrMap.disableAutoScale();
701            }
702      }
703      else if (event.getId() == ScalarMapEvent.MANUAL) {
704            double[] rng = clrMap.getRange();
705            range[0] = rng[0];
706            range[1] = rng[1];
707      }
708    }
709  }
710
711
712}