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