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