001 /* 002 * $Id: HydraCombo.java,v 1.25 2012/02/19 17:35:38 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031 package edu.wisc.ssec.mcidasv.control; 032 033 import java.awt.Color; 034 import java.awt.Container; 035 import java.awt.FlowLayout; 036 import java.awt.event.ActionEvent; 037 import java.awt.event.ActionListener; 038 import java.rmi.RemoteException; 039 import java.util.ArrayList; 040 import java.util.HashMap; 041 import java.util.Hashtable; 042 import java.util.List; 043 import java.util.Map; 044 045 import javax.swing.JButton; 046 import javax.swing.JComboBox; 047 import javax.swing.JComponent; 048 import javax.swing.JLabel; 049 import javax.swing.JPanel; 050 import javax.swing.JTabbedPane; 051 import javax.swing.JTextField; 052 import javax.swing.border.LineBorder; 053 054 import org.python.core.PyObject; 055 056 import visad.ConstantMap; 057 import visad.Data; 058 import visad.VisADException; 059 import visad.georef.MapProjection; 060 061 import ucar.unidata.data.DataChoice; 062 import ucar.unidata.data.DataSource; 063 import ucar.unidata.data.DirectDataChoice; 064 import ucar.unidata.idv.MapViewManager; 065 import ucar.unidata.util.GuiUtils; 066 import ucar.unidata.util.LogUtil; 067 import ucar.unidata.view.geoloc.MapProjectionDisplay; 068 069 import edu.wisc.ssec.mcidasv.Constants; 070 import edu.wisc.ssec.mcidasv.McIDASV; 071 import edu.wisc.ssec.mcidasv.control.LinearCombo.Combination; 072 import edu.wisc.ssec.mcidasv.control.LinearCombo.Selector; 073 import edu.wisc.ssec.mcidasv.data.hydra.MultiDimensionSubset; 074 import edu.wisc.ssec.mcidasv.data.hydra.MultiSpectralData; 075 import edu.wisc.ssec.mcidasv.data.hydra.MultiSpectralDataSource; 076 import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay; 077 import edu.wisc.ssec.mcidasv.jython.Console; 078 import edu.wisc.ssec.mcidasv.jython.ConsoleCallback; 079 080 public class HydraCombo extends HydraControl { 081 082 083 private MultiSpectralDisplay display; 084 085 private DataChoice dataChoice = null; 086 087 private CombinationPanel comboPanel; 088 089 private final Hashtable<String, Object> persistable = new Hashtable<String, Object>(); 090 091 private MultiSpectralDataSource source; 092 093 float init_wavenumber; 094 095 private Map<String, Selector> selectorMap = new HashMap<String, Selector>(); 096 097 private static final String defaultButtonLabel = "Compute New Field"; 098 private JButton computeButton = new JButton(defaultButtonLabel); 099 100 public HydraCombo() { 101 super(); 102 setHelpUrl("idv.controls.hydra.channelcombinationcontrol"); 103 } 104 105 @Override public boolean init(final DataChoice choice) 106 throws VisADException, RemoteException { 107 ((McIDASV)getIdv()).getMcvDataManager().setHydraControl(choice, this); 108 dataChoice = choice; 109 List<DataSource> sources = new ArrayList<DataSource>(); 110 choice.getDataSources(sources); 111 source = ((MultiSpectralDataSource)sources.get(0)); 112 113 Float fieldSelectorChannel = (Float)getDataSelection().getProperty(Constants.PROP_CHAN); 114 if (fieldSelectorChannel == null) 115 fieldSelectorChannel = 0f; 116 init_wavenumber = fieldSelectorChannel; 117 118 display = new MultiSpectralDisplay((DirectDataChoice)choice); 119 display.setWaveNumber(fieldSelectorChannel); 120 display.setDisplayControl(this); 121 122 ((McIDASV)getIdv()).getMcvDataManager().setHydraDisplay(choice, display); 123 124 comboPanel = new CombinationPanel(this); 125 if (!persistable.isEmpty()) { 126 comboPanel.unpersistData(persistable); 127 persistable.clear(); 128 } 129 return true; 130 } 131 132 @Override public void initDone() { 133 MapViewManager viewManager = (MapViewManager) getViewManager(); 134 MapProjectionDisplay dispMaster = 135 (MapProjectionDisplay) viewManager.getMaster(); 136 try { 137 dispMaster.setMapProjection(getDataProjection()); 138 } catch (Exception e) { 139 logException("problem setting MapProjection", e); 140 } 141 142 getIdv().getIdvUIManager().showDashboard(); 143 } 144 145 public Hashtable<String, Object> getPersistable() { 146 return comboPanel.persistData(); 147 } 148 149 public void setPersistable(final Hashtable<String, Object> table) { 150 persistable.clear(); 151 persistable.putAll(table); 152 } 153 154 @Override public MapProjection getDataProjection() { 155 MapProjection mp = null; 156 HashMap subset = null; 157 Hashtable table = dataChoice.getProperties(); 158 MultiDimensionSubset dataSel = 159 (MultiDimensionSubset) table.get(MultiDimensionSubset.key); 160 if (dataSel != null) { 161 subset = dataSel.getSubset(); 162 } 163 mp = source.getDataProjection(subset); 164 return mp; 165 } 166 167 @Override public Container doMakeContents() { 168 JTabbedPane pane = new JTabbedPane(); 169 pane.add("Channel Combination Tool", GuiUtils.inset(getComboTab(), 5)); 170 GuiUtils.handleHeavyWeightComponentsInTabs(pane); 171 return pane; 172 } 173 174 public void updateComboPanel(final String id, final float value) { 175 if (comboPanel == null) 176 return; 177 comboPanel.updateSelector(id, value); 178 } 179 180 protected void enableSelectorForWrapper(final SelectorWrapper wrapper) { 181 if (comboPanel == null) 182 return; 183 comboPanel.enableSelector(wrapper, false); 184 } 185 186 protected void disableSelectorForWrapper(final SelectorWrapper wrapper) { 187 if (comboPanel == null) 188 return; 189 comboPanel.disableSelector(wrapper, false); 190 } 191 192 protected MultiSpectralDisplay getMultiSpectralDisplay() { 193 return display; 194 } 195 196 protected JButton getComputeButton() { 197 return computeButton; 198 } 199 200 private JComponent getComboTab() { 201 computeButton.addActionListener(new ActionListener() { 202 public void actionPerformed(final ActionEvent e) { 203 comboPanel.queueCombination(); 204 computeButton.setEnabled(false); 205 showWaitCursor(); 206 } 207 }); 208 // wrap compute button in JPanel to retain preferred size 209 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); 210 buttonPanel.add(computeButton); 211 JPanel tmp = GuiUtils.topCenterBottom(display.getDisplayComponent(), comboPanel.getPanel(), buttonPanel); 212 return tmp; 213 } 214 215 public void addCombination(final String name, final Data combination) { 216 if (combination != null) 217 source.addChoice(name, combination); 218 } 219 220 public void addCombination(final Combination combination) { 221 if (combination != null) 222 source.addChoice(combination.getName(), combination.getData()); 223 } 224 225 protected void addSelector(final Selector selector) throws Exception { 226 ConstantMap[] mapping = selector.getColor(); 227 float r = new Double(mapping[0].getConstant()).floatValue(); 228 float g = new Double(mapping[1].getConstant()).floatValue(); 229 float b = new Double(mapping[2].getConstant()).floatValue(); 230 Color javaColor = new Color(r, g, b); 231 display.createSelector(selector.getId(), javaColor); 232 display.setSelectorValue(selector.getId(), selector.getWaveNumber()); 233 selectorMap.put(selector.getId(), selector); 234 } 235 236 public void moveSelector(final String id, final float wavenum) { 237 if (!selectorMap.containsKey(id)) 238 return; 239 display.updateControlSelector(id, wavenum); 240 } 241 242 public void updateSelector(final String id, final float wavenum) { 243 if (!selectorMap.containsKey(id)) 244 return; 245 246 selectorMap.get(id).setWaveNumber(wavenum); 247 } 248 249 250 251 public enum DataType { HYPERSPECTRAL, MULTISPECTRAL }; 252 253 public enum WrapperState { ENABLED, DISABLED }; 254 255 public static class CombinationPanel implements ConsoleCallback { 256 private final SelectorWrapper a; 257 private final SelectorWrapper b; 258 private final SelectorWrapper c; 259 private final SelectorWrapper d; 260 261 private final OperationXY ab; 262 private final OperationXY cd; 263 264 private final CombineOperations abcd; 265 266 private final MultiSpectralDisplay display; 267 268 private final HydraCombo control; 269 270 private final Console console; 271 272 private final Map<String, Selector> selectorMap = new HashMap<String, Selector>(); 273 private final Map<String, SelectorWrapper> wrapperMap = new HashMap<String, SelectorWrapper>(); 274 275 private final DataType dataType; 276 277 public CombinationPanel(final HydraCombo control) { 278 this.control = control; 279 display = control.getMultiSpectralDisplay(); 280 if (display == null) 281 throw new NullPointerException("Display hasn't been initialized"); 282 283 MultiSpectralData data = display.getMultiSpectralData(); 284 if (data.hasBandNames()) 285 dataType = DataType.MULTISPECTRAL; 286 else 287 dataType = DataType.HYPERSPECTRAL; 288 289 this.console = new Console(); 290 console.setCallbackHandler(this); 291 292 a = makeWrapper("a", Color.RED); 293 b = makeWrapper("b", Color.GREEN); 294 c = makeWrapper("c", Color.BLUE); 295 d = makeWrapper("d", Color.MAGENTA); 296 297 enableSelector(a, true); 298 299 ab = new OperationXY(this, a, b); 300 cd = new OperationXY(this, c, d); 301 302 abcd = new CombineOperations(this, ab, cd); 303 } 304 305 // public Console getConsole() { 306 // return console; 307 // } 308 309 public void ranBlock(final String line) { 310 PyObject jythonObj = console.getJythonObject("combo"); 311 // if (jythonObj instanceof PyJavaInstance) { 312 Object combination = jythonObj.__tojava__(Object.class); 313 if (combination instanceof Combination) { 314 control.addCombination((Combination)combination); 315 control.getComputeButton().setEnabled(true); 316 control.showNormalCursor(); 317 } 318 // } 319 } 320 321 public void updateSelector(final String id, final float channel) { 322 if (!selectorMap.containsKey(id)) 323 return; 324 325 Selector selector = selectorMap.get(id); 326 selector.setWaveNumber(channel); 327 wrapperMap.get(id).update(); 328 } 329 330 protected void addSelector(final Selector selector, final boolean enabled) throws Exception { 331 String id = selector.getId(); 332 if (enabled) { 333 display.createSelector(id, selector.getColor()); 334 display.setSelectorValue(id, selector.getWaveNumber()); 335 } 336 selectorMap.put(id, selector); 337 } 338 339 protected void disableSelector(final SelectorWrapper wrapper, final boolean disableWrapper) { 340 if (disableWrapper) 341 wrapper.disable(); 342 343 try { 344 display.removeSelector(wrapper.getSelector().getId()); 345 } catch (Exception e) { 346 LogUtil.logException("HydraCombo.disableSelector", e); 347 } 348 } 349 350 protected void enableSelector(final SelectorWrapper wrapper, final boolean enableWrapper) { 351 if (enableWrapper) 352 wrapper.enable(); 353 354 try { 355 Selector selector = wrapper.getSelector(); 356 String id = selector.getId(); 357 display.createSelector(id, selector.getColor()); 358 display.setSelectorValue(id, selector.getWaveNumber()); 359 } catch (Exception e) { 360 LogUtil.logException("HydraCombo.disableSelector", e); 361 } 362 } 363 364 private SelectorWrapper makeWrapper(final String var, final Color color) { 365 try { 366 ConstantMap[] mappedColor = MultiSpectralDisplay.makeColorMap(color); 367 368 SelectorWrapper tmp; 369 if (dataType == DataType.HYPERSPECTRAL) 370 tmp = new HyperspectralSelectorWrapper(var, mappedColor, control, console); 371 else 372 tmp = new MultispectralSelectorWrapper(var, mappedColor, control, console); 373 addSelector(tmp.getSelector(), false); 374 wrapperMap.put(tmp.getSelector().getId(), tmp); 375 // console.injectObject(var, new PyJavaInstance(tmp.getSelector())); 376 console.injectObject(var, tmp.getSelector()); 377 return tmp; 378 } catch (Exception e) { 379 LogUtil.logException("HydraCombo.makeWrapper", e); 380 } 381 return null; 382 } 383 384 public JPanel getPanel() { 385 JPanel panel = new JPanel(new FlowLayout()); 386 panel.add(new JLabel("(")); 387 panel.add(a.getPanel()); 388 panel.add(ab.getBox()); 389 panel.add(b.getPanel()); 390 panel.add(new JLabel(")")); 391 panel.add(abcd.getBox()); 392 panel.add(new JLabel("(")); 393 panel.add(c.getPanel()); 394 panel.add(cd.getBox()); 395 panel.add(d.getPanel()); 396 panel.add(new JLabel(")")); 397 return panel; 398 } 399 400 public void queueCombination() { 401 String jy = "combo="+abcd.getJython(); 402 System.err.println("jython=" + jy); 403 console.queueLine(jy); 404 } 405 406 public Hashtable<String, Object> persistData() { 407 Hashtable<String, Object> table = new Hashtable<String, Object>(); 408 409 table.put("a", a.persistSelectorWrapper()); 410 table.put("b", b.persistSelectorWrapper()); 411 table.put("c", c.persistSelectorWrapper()); 412 table.put("d", d.persistSelectorWrapper()); 413 table.put("ab", ab.getOperation()); 414 table.put("cd", cd.getOperation()); 415 table.put("abcd", abcd.getOperation()); 416 return table; 417 } 418 419 public void unpersistData(final Hashtable<String, Object> table) { 420 Hashtable<String, String> tableA = (Hashtable<String, String>)table.get("a"); 421 Hashtable<String, String> tableB = (Hashtable<String, String>)table.get("b"); 422 Hashtable<String, String> tableC = (Hashtable<String, String>)table.get("c"); 423 Hashtable<String, String> tableD = (Hashtable<String, String>)table.get("d"); 424 425 a.unpersistSelectorWrapper(tableA); 426 b.unpersistSelectorWrapper(tableB); 427 c.unpersistSelectorWrapper(tableC); 428 d.unpersistSelectorWrapper(tableD); 429 430 String opAb = (String)table.get("ab"); 431 String opCd = (String)table.get("cd"); 432 String opAbcd = (String)table.get("abcd"); 433 434 ab.setOperation(opAb); 435 cd.setOperation(opCd); 436 abcd.setOperation(opAbcd); 437 } 438 } 439 440 private static class OperationXY { 441 private static final String[] OPERATIONS = { "+", "-", "/", "*", " " }; 442 private static final String INVALID_OP = " "; 443 private final JComboBox combo = new JComboBox(OPERATIONS); 444 445 private CombinationPanel comboPanel; 446 private SelectorWrapper x; 447 private SelectorWrapper y; 448 449 public OperationXY(final CombinationPanel comboPanel, final SelectorWrapper x, final SelectorWrapper y) { 450 this.x = x; 451 this.y = y; 452 this.comboPanel = comboPanel; 453 combo.setSelectedItem(" "); 454 combo.addActionListener(new ActionListener() { 455 public void actionPerformed(final ActionEvent e) { 456 if (getOperation().equals(" ")) { 457 comboPanel.disableSelector(y, true); 458 } else { 459 comboPanel.enableSelector(y, true); 460 } 461 } 462 }); 463 } 464 465 public void disable() { 466 comboPanel.disableSelector(x, true); 467 combo.setSelectedItem(INVALID_OP); 468 comboPanel.disableSelector(y, true); 469 } 470 471 public void enable() { 472 comboPanel.enableSelector(x, true); 473 } 474 475 public String getOperation() { 476 return (String)combo.getSelectedItem(); 477 } 478 479 public void setOperation(final String operation) { 480 combo.setSelectedItem(operation); 481 } 482 483 public JComboBox getBox() { 484 return combo; 485 } 486 487 public String getJython() { 488 String operation = getOperation(); 489 if (operation.equals(INVALID_OP)) 490 operation = ""; 491 492 String jython = x.getJython() + operation + y.getJython(); 493 if (x.isValid() && y.isValid()) 494 return "(" + jython + ")"; 495 return jython; 496 } 497 } 498 499 private static class CombineOperations { 500 private static final String[] OPERATIONS = { "+", "-", "/", "*", " "}; 501 private static final String INVALID_OP = " "; 502 private final JComboBox combo = new JComboBox(OPERATIONS); 503 504 private OperationXY x; 505 private OperationXY y; 506 507 public CombineOperations(final CombinationPanel comboPanel, final OperationXY x, final OperationXY y) { 508 this.x = x; 509 this.y = y; 510 combo.setSelectedItem(INVALID_OP); 511 combo.addActionListener(new ActionListener() { 512 public void actionPerformed(final ActionEvent e) { 513 if (getOperation().equals(" ")) { 514 y.disable(); 515 } else { 516 y.enable(); 517 } 518 } 519 }); 520 } 521 522 public String getOperation() { 523 return (String)combo.getSelectedItem(); 524 } 525 526 public void setOperation(final String operation) { 527 combo.setSelectedItem(operation); 528 } 529 530 public JComboBox getBox() { 531 return combo; 532 } 533 534 public String getJython() { 535 String operation = getOperation(); 536 if (operation.equals(INVALID_OP)) 537 operation = ""; 538 539 String jython = x.getJython() + operation + y.getJython(); 540 return jython; 541 } 542 } 543 544 private static abstract class SelectorWrapper { 545 protected static final String BLANK = "-----"; 546 private String variable; 547 private final ConstantMap[] color; 548 protected final Selector selector; 549 protected final MultiSpectralDisplay display; 550 protected final MultiSpectralData data; 551 private final JTextField scale = new JTextField(String.format("%3.1f", 1.0)); 552 protected WrapperState currentState = WrapperState.DISABLED; 553 554 public SelectorWrapper(final String variable, final ConstantMap[] color, final HydraCombo control, final Console console) { 555 this.display = control.getMultiSpectralDisplay(); 556 this.data = control.getMultiSpectralDisplay().getMultiSpectralData(); 557 this.variable = variable; 558 this.color = color; 559 this.selector = new Selector(control.init_wavenumber, color, control, console); 560 this.selector.addName(variable); 561 } 562 563 public Selector getSelector() { 564 return selector; 565 } 566 567 public JPanel getPanel() { 568 JPanel panel = new JPanel(new FlowLayout()); 569 JComponent comp = getWavenumberComponent(); 570 float r = new Double(color[0].getConstant()).floatValue(); 571 float g = new Double(color[1].getConstant()).floatValue(); 572 float b = new Double(color[2].getConstant()).floatValue(); 573 comp.setBorder(new LineBorder(new Color(r, g, b), 2)); 574 panel.add(scale); 575 panel.add(comp); 576 return panel; 577 } 578 579 public String getJython() { 580 if (!isValid()) 581 return ""; 582 return "(" + scale.getText() + "*" + variable + ")"; 583 } 584 585 public boolean isValid() { 586 return !getValue().equals(BLANK); 587 } 588 589 public void enable() { 590 setValue(Float.toString(selector.getWaveNumber())); 591 currentState = WrapperState.ENABLED; 592 } 593 594 public void disable() { 595 setValue(BLANK); 596 currentState = WrapperState.DISABLED; 597 } 598 599 public void update() { 600 setValue(Float.toString(selector.getWaveNumber())); 601 } 602 603 public Hashtable<String, String> persistSelectorWrapper() { 604 Hashtable<String, String> table = new Hashtable<String, String>(3); 605 String scaleText = scale.getText(); 606 String waveText = getValue(); 607 608 if (scaleText == null || scaleText.length() == 0) 609 scaleText = "1.0"; 610 if (waveText == null || waveText.length() == 0 || !isValid()) 611 waveText = BLANK; 612 613 table.put("variable", variable); 614 table.put("scale", scale.getText()); 615 table.put("wave", getValue()); 616 return table; 617 } 618 619 public void unpersistSelectorWrapper(final Hashtable<String, String> table) { 620 variable = table.get("variable"); 621 selector.addName(variable); 622 scale.setText(String.format("%3.1f", new Float(table.get("scale")))); 623 624 String waveText = table.get("wave"); 625 if (waveText.equals(BLANK)) { 626 disable(); 627 } else { 628 float wave = new Float(table.get("wave")); 629 selector.setWaveNumber(wave); 630 if (isValid()) 631 update(); 632 } 633 } 634 635 public abstract JComponent getWavenumberComponent(); 636 637 public abstract void setValue(final String value); 638 639 public abstract String getValue(); 640 } 641 642 private static class HyperspectralSelectorWrapper extends SelectorWrapper { 643 private final JTextField wavenumber; 644 public HyperspectralSelectorWrapper(final String variable, final ConstantMap[] color, final HydraCombo control, final Console console) { 645 super(variable, color, control, console); 646 wavenumber = new JTextField(BLANK, 7); 647 648 wavenumber.addActionListener(new ActionListener() { 649 public void actionPerformed(final ActionEvent e) { 650 String textVal = wavenumber.getText(); 651 if (textVal.equals(BLANK)) 652 return; 653 654 float wave = Float.parseFloat(textVal.trim()); 655 control.updateComboPanel(getSelector().getId(), wave); 656 } 657 }); 658 } 659 660 @Override public JComponent getWavenumberComponent() { 661 return wavenumber; 662 } 663 664 @Override public void setValue(final String value) { 665 if (value == null) 666 throw new NullPointerException(""); 667 668 if (!value.equals(BLANK)) { 669 float wave = Float.parseFloat(value); 670 String fmt = String.format("%7.2f", wave); 671 wavenumber.setText(fmt); 672 } 673 } 674 675 public String getValue() { 676 return wavenumber.getText(); 677 } 678 } 679 680 private static class MultispectralSelectorWrapper extends SelectorWrapper { 681 682 private final JComboBox bands; 683 684 public MultispectralSelectorWrapper(final String variable, final ConstantMap[] color, final HydraCombo control, final Console console) { 685 super(variable, color, control, console); 686 removeMSDListeners(); 687 bands = bigBadBox(control); 688 } 689 690 private void removeMSDListeners() { 691 JComboBox box = display.getBandSelectComboBox(); 692 for (ActionListener l : box.getActionListeners()) 693 box.removeActionListener(l); 694 } 695 696 private JComboBox bigBadBox(final HydraCombo control) { 697 final JComboBox box = new JComboBox(); 698 box.addItem(BLANK); 699 700 for (String name : data.getBandNames()) 701 box.addItem(name); 702 703 final SelectorWrapper wrapper = this; 704 box.addActionListener(new ActionListener() { 705 public void actionPerformed(final ActionEvent e) { 706 String selected = (String)box.getSelectedItem(); 707 float wave = Float.NaN; 708 709 if (!selected.equals(BLANK)) { 710 Map<String, Float> map = data.getBandNameMap(); 711 if (map.containsKey(selected)) 712 wave = map.get(selected); 713 714 if (currentState == WrapperState.DISABLED) 715 control.enableSelectorForWrapper(wrapper); 716 control.updateComboPanel(getSelector().getId(), wave); 717 } else { 718 control.disableSelectorForWrapper(wrapper); 719 } 720 } 721 }); 722 723 return box; 724 } 725 726 @Override public JComponent getWavenumberComponent() { 727 return bands; 728 } 729 730 @Override public void setValue(final String value) { 731 if (value == null) 732 throw new NullPointerException(); 733 734 if (!value.equals(BLANK)) { 735 String name = data.getBandNameFromWaveNumber(Float.parseFloat(value)); 736 bands.setSelectedItem(name); 737 } else { 738 bands.setSelectedItem(BLANK); 739 } 740 } 741 742 @Override public String getValue() { 743 return (String)bands.getSelectedItem(); 744 } 745 } 746 }