001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2017 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 */ 028 029package edu.wisc.ssec.mcidasv.control; 030 031import java.awt.Color; 032import java.awt.Component; 033import java.awt.Dimension; 034import java.awt.Font; 035import java.awt.FontMetrics; 036import java.awt.GridBagConstraints; 037import java.awt.GridBagLayout; 038import java.awt.Image; 039import java.awt.event.ActionEvent; 040import java.awt.event.ActionListener; 041import java.awt.event.ItemEvent; 042import java.awt.event.ItemListener; 043import java.awt.event.KeyAdapter; 044import java.awt.event.KeyEvent; 045import java.awt.event.MouseAdapter; 046import java.awt.event.MouseEvent; 047import java.io.BufferedReader; 048import java.io.DataInputStream; 049import java.io.InputStreamReader; 050import java.net.URLEncoder; 051import java.rmi.RemoteException; 052import java.util.ArrayList; 053import java.util.Hashtable; 054import java.util.List; 055import java.util.StringTokenizer; 056 057import javax.swing.BorderFactory; 058import javax.swing.JCheckBox; 059import javax.swing.JComponent; 060import javax.swing.JLabel; 061import javax.swing.JPanel; 062import javax.swing.JScrollBar; 063import javax.swing.JScrollPane; 064import javax.swing.JTabbedPane; 065import javax.swing.JTextField; 066import javax.swing.JTextPane; 067import javax.swing.ScrollPaneConstants; 068import javax.swing.SwingUtilities; 069import javax.swing.border.EmptyBorder; 070import javax.swing.text.BadLocationException; 071import javax.swing.text.Style; 072import javax.swing.text.StyleConstants; 073import javax.swing.text.StyledDocument; 074 075import visad.VisADException; 076import visad.georef.MapProjection; 077 078import ucar.unidata.data.DataChoice; 079import ucar.unidata.data.DataContext; 080import ucar.unidata.data.DataSource; 081import ucar.unidata.data.DataSourceImpl; 082import ucar.unidata.idv.ControlContext; 083import ucar.unidata.idv.IntegratedDataViewer; 084import ucar.unidata.idv.MapViewManager; 085import ucar.unidata.idv.control.ControlWidget; 086import ucar.unidata.idv.control.ImageSequenceControl; 087import ucar.unidata.idv.control.WrapperWidget; 088import ucar.unidata.ui.colortable.ColorTableManager; 089import ucar.unidata.util.ColorTable; 090import ucar.unidata.util.GuiUtils; 091import ucar.unidata.util.Misc; 092 093import edu.wisc.ssec.mcidasv.data.FrameDirtyInfo; 094import edu.wisc.ssec.mcidasv.data.McIdasFrame; 095import edu.wisc.ssec.mcidasv.data.McIdasXDataSource; 096import edu.wisc.ssec.mcidasv.data.McIdasXInfo; 097import edu.wisc.ssec.mcidasv.ui.McIdasFrameDisplay; 098 099/** 100 * A DisplayControl for handling McIDAS-X image sequences 101 */ 102public class McIdasImageSequenceControl extends ImageSequenceControl { 103 104 private JLabel runningThreads; 105 private JCheckBox navigatedCbx; 106 private JPanel frameNavigatedContent; 107 private McIdasFrameDisplay frameDisplay; 108 private Dimension frameSize; 109 private JTextField inputText; 110 private JScrollPane outputPane; 111 private StyledDocument outputText; 112 private Font outputFont = new Font("Monospaced", Font.BOLD, 12); 113 private ArrayList commandHistory = new ArrayList(); 114 private int commandHistoryIdx = -1; 115 private boolean commandHistoryMode = true; 116 117 /** McIDAS-X handles */ 118 private McIdasXInfo mcidasxInfo; 119 private McIdasXDataSource mcidasxDS; 120 121 private int threadCount = 0; 122 123 private static DataChoice dc=null; 124 private static Integer frmI; 125 126 /** Holds frame component information */ 127 private FrameComponentInfo frameComponentInfo; 128 private List frameDirtyInfoList = new ArrayList(); 129 private List frameNumbers = new ArrayList(); 130 131 /** 132 * Default ctor; sets the attribute flags 133 */ 134 public McIdasImageSequenceControl() { 135 setAttributeFlags(FLAG_COLORTABLE | FLAG_DISPLAYUNIT); 136 initFrameComponentInfo(); 137 this.mcidasxInfo = null; 138 this.mcidasxDS = null; 139 140 setDisplayId("bridgecontrol"); 141 setHelpUrl("idv.controls.bridgecontrol"); 142 143 setExpandedInTabs(true); 144 } 145 146 /** 147 * Creates, if needed, the frameComponentInfo member. 148 */ 149 private void initFrameComponentInfo() { 150 if (this.frameComponentInfo == null) { 151 this.frameComponentInfo = new FrameComponentInfo(true, true, true, false, true, false); 152 } 153 } 154 155 /** 156 * Initializes the frameDirtyInfoList member. 157 */ 158 private void initFrameDirtyInfoList() { 159 this.frameDirtyInfoList.clear(); 160 Integer frameNumber; 161 FrameDirtyInfo frameDirtyInfo; 162 for (int i=0; i<this.frameNumbers.size(); i++) { 163 frameNumber = (Integer)this.frameNumbers.get(i); 164 frameDirtyInfo = new FrameDirtyInfo(frameNumber.intValue(), false, false, false); 165 this.frameDirtyInfoList.add(frameDirtyInfo); 166 } 167 } 168 169 /** 170 * Sets the frameDirtyInfoList member based on frame number 171 */ 172 private void setFrameDirtyInfoList(int frameNumber, boolean dirtyImage, boolean dirtyGraphics, boolean dirtyColorTable) { 173 FrameDirtyInfo frameDirtyInfo; 174 for (int i=0; i<this.frameDirtyInfoList.size(); i++) { 175 frameDirtyInfo = (FrameDirtyInfo)frameDirtyInfoList.get(i); 176 if (frameDirtyInfo.getFrameNumber() == frameNumber) { 177 frameDirtyInfo.setDirtyImage(dirtyImage); 178 frameDirtyInfo.setDirtyGraphics(dirtyGraphics); 179 frameDirtyInfo.setDirtyColorTable(dirtyColorTable); 180 this.frameDirtyInfoList.set(i, frameDirtyInfo); 181 } 182 } 183 } 184 185 /** 186 * Override the base class method that creates request properties 187 * and add in the appropriate frame component request parameters. 188 * @return table of properties 189 */ 190 protected Hashtable getRequestProperties() { 191 Hashtable props = super.getRequestProperties(); 192 props.put(McIdasComponents.IMAGE, new Boolean(this.frameComponentInfo.getIsImage())); 193 props.put(McIdasComponents.GRAPHICS, new Boolean(this.frameComponentInfo.getIsGraphics())); 194 props.put(McIdasComponents.COLORTABLE, new Boolean(this.frameComponentInfo.getIsColorTable())); 195 props.put(McIdasComponents.ANNOTATION, new Boolean(this.frameComponentInfo.getIsAnnotation())); 196 props.put(McIdasComponents.FAKEDATETIME, new Boolean(this.frameComponentInfo.getFakeDateTime())); 197 props.put(McIdasComponents.DIRTYINFO, this.frameDirtyInfoList); 198 return props; 199 } 200 201 /** 202 * A helper method for constructing the ui. 203 * This fills up a list of {@link ControlWidget} 204 * (e.g., ColorTableWidget) and creates a gridded 205 * ui with them. 206 * 207 * @return The ui for the widgets 208 */ 209 protected JComponent doMakeWidgetComponent() { 210 211 JPanel framePanel = new JPanel(); 212 try { 213 framePanel = GuiUtils.top(doMakeFramePanel()); 214 } catch (Exception e) { 215 System.err.println("doMakeContents exception: " + e); 216 } 217 218 JComponent settingsPanel = GuiUtils.top(super.doMakeWidgetComponent()); 219 220 JTabbedPane tabbedPane = new JTabbedPane(); 221 tabbedPane.add("Frames", framePanel); 222 tabbedPane.add("Settings", settingsPanel); 223 224 return tabbedPane; 225 226 } 227 228 /** 229 * Get control widgets specific to this control. 230 * 231 * @param controlWidgets list of control widgets from other places 232 * 233 * @throws RemoteException Java RMI error 234 * @throws VisADException VisAD Error 235 */ 236 public void getControlWidgets(List controlWidgets) 237 throws VisADException, RemoteException { 238 239 super.getControlWidgets(controlWidgets); 240 241 // Navigated checkbox 242 navigatedCbx = new JCheckBox("Display data in main 3D panel", false); 243 navigatedCbx.setToolTipText("Set to send navigated data to the main 3D display in addition to this 2D display"); 244 navigatedCbx.addItemListener(new ItemListener() { 245 public void itemStateChanged(ItemEvent e) { 246 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 247 GuiUtils.enableTree(frameNavigatedContent, myself.isSelected()); 248 updateVImage(); 249 } 250 }); 251 JPanel frameNavigatedCbx = 252 GuiUtils.hflow(Misc.newList(navigatedCbx), 2, 0); 253 controlWidgets.add( 254 new WrapperWidget( this, GuiUtils.rLabel("Data:"), frameNavigatedCbx)); 255 256 // Navigated options 257 JPanel frameComponentsPanel = 258 GuiUtils.hflow(Misc.newList(doMakeImageBox(), doMakeGraphicsBox(), doMakeAnnotationBox()), 2, 0); 259 JPanel frameOrderPanel = 260 GuiUtils.hflow(Misc.newList(doMakeFakeDateTimeBox()), 2, 0); 261 JPanel frameProjectionPanel = 262 GuiUtils.hflow(Misc.newList(doMakeResetProjectionBox()), 2, 0); 263 frameNavigatedContent = 264 GuiUtils.vbox(frameComponentsPanel, frameOrderPanel, frameProjectionPanel); 265 GuiUtils.enableTree(frameNavigatedContent, false); 266 controlWidgets.add( 267 new WrapperWidget( this, GuiUtils.rLabel(""), frameNavigatedContent)); 268 269 } 270 271 /** 272 * Get frame control widgets specific to this control. 273 * 274 * @throws RemoteException Java RMI error 275 * @throws VisADException VisAD Error 276 */ 277 private JPanel doMakeFramePanel() 278 throws VisADException, RemoteException { 279 frameSize = new Dimension(640, 480); 280 281 JPanel framePanel = new JPanel(new GridBagLayout()); 282 GridBagConstraints c = new GridBagConstraints(); 283 c.gridwidth = GridBagConstraints.REMAINDER; 284 285 frmI = new Integer(0); 286 ControlContext controlContext = getControlContext(); 287 List dss = ((IntegratedDataViewer)controlContext).getDataSources(); 288 for (int i=0; i<dss.size(); i++) { 289 DataSourceImpl ds = (DataSourceImpl)dss.get(i); 290 if (ds instanceof McIdasXDataSource) { 291 frameNumbers.clear(); 292 ds.setProperty(DataSource.PROP_AUTOCREATEDISPLAY, false); 293 mcidasxDS = (McIdasXDataSource)ds; 294 DataContext dataContext = mcidasxDS.getDataContext(); 295 ColorTableManager colorTableManager = 296 ((IntegratedDataViewer)dataContext).getColorTableManager(); 297 ColorTable ct = colorTableManager.getColorTable("McIDAS-X"); 298 setColorTable(ct); 299 this.mcidasxInfo = mcidasxDS.getMcIdasXInfo(); 300 this.dc = getDataChoice(); 301 String choiceStr = this.dc.toString(); 302 if (choiceStr.equals("Frame Sequence")) { 303 frameNumbers = mcidasxDS.getFrameNumbers(); 304 } else { 305 StringTokenizer tok = new StringTokenizer(choiceStr); 306 String str = tok.nextToken(); 307 if (str.equals("Frame")) { 308 frmI = new Integer(tok.nextToken()); 309 frameNumbers.add(frmI); 310 } else { 311 frmI = new Integer(1); 312 frameNumbers.add(frmI); 313 } 314 } 315 break; 316 } 317 } 318 initFrameDirtyInfoList(); 319 320 // McIDAS-X frame display 321 frameDisplay = new McIdasFrameDisplay(frameNumbers, frameSize); 322 for (int i=0; i<frameNumbers.size(); i++) { 323 updateXImage((Integer)frameNumbers.get(i)); 324 if (i==0) showXImage((Integer)frameNumbers.get(i)); 325 } 326 framePanel.add(GuiUtils.hflow(Misc.newList(frameDisplay)), c); 327 328 // McIDAS-X text stuff 329 outputPane = doMakeOutputText(); 330 inputText = doMakeCommandLine(); 331 JPanel commandLinePanel = 332 GuiUtils.vbox(outputPane, doMakeSpacer(), inputText); 333 commandLinePanel.setBorder(BorderFactory.createLineBorder(Color.black)); 334 framePanel.add(GuiUtils.hflow(Misc.newList(commandLinePanel)), c); 335 336 // McIDAS-X commands that are running 337 runningThreads = GuiUtils.lLabel("Running: " + this.threadCount); 338 framePanel.add(GuiUtils.hflow(Misc.newList(runningThreads)), c); 339 340 // Create a sensible title and tell McIDAS-X to stop looping and go to the first frame 341 String title = ""; 342 if (frameNumbers.size() == 1) { 343 title = "McIDAS-X Frame " + (Integer)frameNumbers.get(0); 344 } 345 else { 346 Integer first = (Integer)frameNumbers.get(0); 347 Integer last = (Integer)frameNumbers.get(frameNumbers.size() - 1); 348 if (last - first == frameNumbers.size() - 1) { 349 title = "McIDAS-X Frames " + first + "-" + last; 350 } 351 else { 352 title = "McIDAS-X Frames " + (Integer)frameNumbers.get(0); 353 for (int i=1; i<frameNumbers.size(); i++) { 354 title += ", " + (Integer)frameNumbers.get(i); 355 } 356 } 357 } 358 sendCommandLine("TERM L OFF; SF " + (Integer)frameNumbers.get(0), false); 359 360 setNameFromUser(title); 361 362 // Give inputText the focus whenever anything is clicked on... 363 framePanel.addMouseListener(new MouseAdapter() { 364 public void mouseClicked(MouseEvent me) { 365 if (me.getButton() == me.BUTTON1) { 366 inputText.requestFocus(); 367 } 368 } 369 }); 370 371 return framePanel; 372 } 373 374 /** 375 * Make the frame component check boxes. 376 * @return Check box for Images 377 */ 378 protected Component doMakeImageBox() { 379 JCheckBox newBox = new JCheckBox("Image", frameComponentInfo.getIsImage()); 380 newBox.setToolTipText("Set to import image data"); 381 newBox.addItemListener(new ItemListener() { 382 public void itemStateChanged(ItemEvent e) { 383 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 384 frameComponentInfo.setIsImage(myself.isSelected()); 385 updateVImage(); 386 } 387 }); 388 return newBox; 389 } 390 391 /** 392 * Make the frame component check boxes. 393 * @return Check box for Graphics 394 */ 395 protected Component doMakeGraphicsBox() { 396 JCheckBox newBox = new JCheckBox("Graphics", frameComponentInfo.getIsGraphics()); 397 newBox.setToolTipText("Set to import graphics data"); 398 newBox.addItemListener(new ItemListener() { 399 public void itemStateChanged(ItemEvent e) { 400 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 401 frameComponentInfo.setIsGraphics(myself.isSelected()); 402 updateVImage(); 403 } 404 }); 405 return newBox; 406 } 407 408 /** 409 * Make the frame component check boxes. 410 * @return Check box for Color table 411 */ 412 protected Component doMakeColorTableBox() { 413 JCheckBox newBox = new JCheckBox("Color table", frameComponentInfo.getIsColorTable()); 414 newBox.setToolTipText("Set to import color table data"); 415 newBox.addItemListener(new ItemListener() { 416 public void itemStateChanged(ItemEvent e) { 417 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 418 frameComponentInfo.setIsColorTable(myself.isSelected()); 419 updateVImage(); 420 } 421 }); 422 return newBox; 423 } 424 425 /** 426 * Make the frame component check boxes. 427 * @return Check box for Annotation line 428 */ 429 protected Component doMakeAnnotationBox() { 430 JCheckBox newBox = new JCheckBox("Annotation line", frameComponentInfo.getIsAnnotation()); 431 newBox.setToolTipText("Set to import annotation line"); 432 newBox.addItemListener(new ItemListener() { 433 public void itemStateChanged(ItemEvent e) { 434 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 435 frameComponentInfo.setIsAnnotation(myself.isSelected()); 436 updateVImage(); 437 } 438 }); 439 return newBox; 440 } 441 442 /** 443 * Make the frame behavior check boxes. 444 * @return Check box for Fake date/time 445 */ 446 protected Component doMakeFakeDateTimeBox() { 447 JCheckBox newBox = 448 new JCheckBox("Use McIDAS-X frame order to override data time with frame number", 449 frameComponentInfo.getFakeDateTime()); 450 newBox.setToolTipText("Set to preserve frame order"); 451 newBox.addItemListener(new ItemListener() { 452 public void itemStateChanged(ItemEvent e) { 453 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 454 frameComponentInfo.setFakeDateTime(myself.isSelected()); 455 updateVImage(); 456 } 457 }); 458 return newBox; 459 } 460 461 /** 462 * Make the frame behavior check boxes. 463 * @return Check box for Projection reset 464 */ 465 protected Component doMakeResetProjectionBox() { 466 JCheckBox newBox = 467 new JCheckBox("Use McIDAS-X data projection", 468 frameComponentInfo.getResetProjection()); 469 newBox.setToolTipText("Set to reset projection when data is refreshed"); 470 newBox.addItemListener(new ItemListener() { 471 public void itemStateChanged(ItemEvent e) { 472 JCheckBox myself = (JCheckBox)e.getItemSelectable(); 473 frameComponentInfo.setResetProjection(myself.isSelected()); 474 updateVImage(); 475 } 476 }); 477 return newBox; 478 } 479 480 private void resetCommandHistory() { 481 commandHistory = new ArrayList(); 482 resetCommandHistoryIdx(); 483 } 484 485 private void resetCommandHistoryIdx() { 486 commandHistoryIdx = -1; 487 } 488 489 protected JTextField doMakeCommandLine() { 490 final JTextField commandLine = new JTextField(0); 491 commandLine.setFont(outputFont); 492 commandLine.setBackground(Color.black); 493 commandLine.setForeground(Color.cyan); 494 commandLine.setCaretColor(Color.cyan); 495 496 FontMetrics metrics = commandLine.getFontMetrics(outputFont); 497 Dimension d = new Dimension(frameSize.width, metrics.getHeight()); 498 commandLine.setSize(d); 499 commandLine.setPreferredSize(d); 500 commandLine.setMinimumSize(d); 501 commandLine.setMaximumSize(d); 502 503 resetCommandHistory(); 504 505 commandLine.addActionListener(new ActionListener() { 506 public void actionPerformed(ActionEvent ae) { 507 String line = commandLine.getText().trim(); 508 if (line.equals("")) return; 509 commandLine.setText(""); 510 sendCommandLineThread(line, true); 511 512 // Add it to the head of commandHistory list 513 commandHistory.add(0, line); 514 resetCommandHistoryIdx(); 515 } 516 }); 517 commandLine.addKeyListener(new KeyAdapter() { 518 public void keyTyped(KeyEvent ke) { 519 char keyChar = ke.getKeyChar(); 520 if (commandLine.getText().trim().equals("") && commandHistory.size() > 0) { 521 commandHistoryMode = true; 522 } 523 if (commandHistoryMode) { 524 if (keyChar == '&') { 525 commandHistoryIdx = Math.min(commandHistoryIdx+1,commandHistory.size()-1); 526 if (commandHistoryIdx < 0) { 527 resetCommandHistoryIdx(); 528 commandLine.setText(""); 529 } 530 else { 531 commandLine.setText((String)commandHistory.get(commandHistoryIdx)); 532 } 533 ke.consume(); 534 } 535 else if (keyChar == '^') { 536 commandHistoryIdx--; 537 if (commandHistoryIdx < 0) { 538 resetCommandHistoryIdx(); 539 commandLine.setText(""); 540 } 541 else { 542 commandLine.setText((String)commandHistory.get(commandHistoryIdx)); 543 } 544 ke.consume(); 545 } 546 else { 547 commandHistoryMode = false; 548 } 549 } 550 if (Character.isLowerCase(keyChar)) 551 keyChar = Character.toUpperCase(keyChar); 552 else 553 keyChar = Character.toLowerCase(keyChar); 554 ke.setKeyChar(keyChar); 555 } 556 }); 557 commandLine.setBorder(new EmptyBorder(0,0,0,0)); 558 return commandLine; 559 } 560 561 private Component doMakeSpacer() { 562 JPanel spacer = new JPanel(); 563 Color backgroundColor = new Color(0, 128, 128); 564 spacer.setBackground(backgroundColor); 565 FontMetrics metrics = inputText.getFontMetrics(outputFont); 566 Dimension d = new Dimension(frameSize.width, metrics.getHeight()); 567 spacer.setSize(d); 568 spacer.setPreferredSize(d); 569 spacer.setMinimumSize(d); 570 spacer.setMaximumSize(d); 571 spacer.setBorder(new EmptyBorder(0,0,0,0)); 572 return spacer; 573 } 574 575 protected JScrollPane doMakeOutputText() { 576 JTextPane outputPane = new JTextPane() { 577 public void setSize(Dimension d) { 578 if (d.width < getParent().getSize().width) 579 d.width = getParent().getSize().width; 580 super.setSize(d); 581 } 582 public boolean getScrollableTracksViewportWidth() { 583 return false; 584 } 585 }; 586 outputPane.setFont(outputFont); 587 outputPane.setEditable(false); 588 outputPane.setBackground(Color.black); 589 outputPane.setForeground(Color.lightGray); 590 JScrollPane outputScrollPane = new JScrollPane(outputPane, 591 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, 592 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 593 594 FontMetrics metrics = outputPane.getFontMetrics(outputFont); 595 Dimension d = new Dimension(frameSize.width, metrics.getHeight() * 8); 596 outputScrollPane.setSize(d); 597 outputScrollPane.setPreferredSize(d); 598 outputScrollPane.setMinimumSize(d); 599 outputScrollPane.setMaximumSize(d); 600 601 outputText = (StyledDocument)outputPane.getDocument(); 602 outputScrollPane.setBorder(new EmptyBorder(0,0,0,0)); 603 604 return outputScrollPane; 605 } 606 607 /** 608 * Send the given commandline to McIDAS-X over the bridge 609 * @param line 610 * @param showprocess 611 */ 612 private void sendCommandLine(String line, boolean showprocess) { 613 614 // The user might have moved to another frame... 615 // Ask the image display which frame we are on 616 int frameCur = 1; 617 if (frameDisplay != null) 618 frameCur = frameDisplay.getFrameNumber(); 619 620 line = line.trim(); 621 if (line.length() < 1) return; 622 String encodedLine = line; 623 try { 624 encodedLine = URLEncoder.encode(line,"UTF-8"); 625 } catch (Exception e) { 626 System.out.println("sendCommandLine URLEncoder exception: " + e); 627 } 628 629 DataInputStream inputStream = mcidasxInfo.getCommandInputStream(encodedLine, frameCur); 630 if (!showprocess) { 631 try { inputStream.close(); } 632 catch (Exception e) {} 633 return; 634 } 635// appendTextLineItalics(line); 636 appendTextLineCommand(line); 637 try { 638 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); 639 String responseType = null; 640 String ULine = null; 641 StringTokenizer tok; 642 boolean inList = false; 643 boolean doUpdate = false; 644 boolean dirtyImage, dirtyGraphics, dirtyColorTable; 645 // Burn the session key header line 646 String lineOut = br.readLine(); 647 lineOut = br.readLine(); 648 while (lineOut != null) { 649// System.out.println("sendCommandLine processing: " + lineOut); 650 tok = new StringTokenizer(lineOut, " "); 651 responseType = tok.nextToken(); 652 if (responseType.equals("U")) { 653 Integer frameInt = (Integer)Integer.parseInt(tok.nextToken()); 654 inList = false; 655 dirtyImage = dirtyGraphics = dirtyColorTable = false; 656 // Don't pay attention to anything outside of our currently loaded frame list 657 for (int i=0; i<frameNumbers.size(); i++) { 658 if (frameInt.compareTo((Integer)frameNumbers.get(i)) == 0) inList = true; 659 } 660 if (inList) { 661 ULine = tok.nextToken(); 662// System.out.println(" Frame " + frameInt + " status line: " + ULine); 663 if (Integer.parseInt(ULine.substring(1,2)) != 0) dirtyImage = true; 664 if (Integer.parseInt(ULine.substring(3,4)) != 0) dirtyGraphics = true; 665 if (Integer.parseInt(ULine.substring(5,6)) != 0) dirtyColorTable = true; 666 if (dirtyImage || dirtyGraphics || dirtyColorTable) { 667 doUpdate = true; 668 updateXImage(frameInt); 669 } 670 setFrameDirtyInfoList(frameInt, dirtyImage, dirtyGraphics, dirtyColorTable); 671 } 672 } else if (responseType.equals("C")) { 673 appendTextLineCommand(lineOut.substring(6)); 674 } else if (responseType.equals("T")) { 675// appendTextLine(" " + lineOut.substring(6)); 676 appendTextLineNormal(lineOut.substring(6)); 677 678 } else if (responseType.equals("M") || 679 responseType.equals("S")) { 680// appendTextLine(" * " + lineOut.substring(6)); 681 appendTextLineError(lineOut.substring(6)); 682 683 } else if (responseType.equals("R")) { 684// appendTextLine(" ! " + lineOut.substring(6)); 685 appendTextLineError(lineOut.substring(6)); 686 } else if (responseType.equals("V")) { 687// System.out.println("Viewing frame status line: " + lineOut); 688 frameCur = Integer.parseInt(tok.nextToken()); 689 } else if (responseType.equals("H") || 690 responseType.equals("K")) { 691 /* Don't do anything with these response types */ 692 } else { 693 /* Catch any unparsed line... */ 694 System.err.println("Could not parse bridge response: " + lineOut); 695 } 696 lineOut = br.readLine(); 697 } 698 showXImage(frameCur); 699 if (doUpdate) { 700 updateVImage(); 701 } 702 703 } catch (Exception e) { 704 System.out.println("sendCommandLine exception: " + e); 705 try { inputStream.close(); } 706 catch (Exception ee) {} 707 } 708 709 } 710 711/* 712 private void appendTextLine(String line) { 713 outputText.append(line + "\n"); 714 outputText.setCaretPosition(outputText.getDocument().getLength()); 715 } 716*/ 717 718 private void appendTextLineNormal(String line) { 719 Style style = outputText.addStyle("Normal", null); 720 StyleConstants.setForeground(style, Color.lightGray); 721 try { 722 outputText.insertString(outputText.getLength(), line + "\n", style); 723 } catch (BadLocationException e) { } 724 scrollTextLineToBottom(); 725 } 726 727 private void appendTextLineCommand(String line) { 728 Style style = outputText.addStyle("Command", null); 729 StyleConstants.setForeground(style, Color.green); 730 try { 731 outputText.insertString(outputText.getLength(), line + "\n", style); 732 } catch (BadLocationException e) { } 733 scrollTextLineToBottom(); 734 } 735 736 private void appendTextLineError(String line) { 737 Style style = outputText.addStyle("Error", null); 738 StyleConstants.setForeground(style, Color.yellow); 739 try { 740 outputText.insertString(outputText.getLength(), line + "\n", style); 741 } catch (BadLocationException e) { } 742 scrollTextLineToBottom(); 743 } 744 745 private void scrollTextLineToBottom() { 746 SwingUtilities.invokeLater(new Runnable() { 747 public void run() { 748 JScrollBar vBar = outputPane.getVerticalScrollBar(); 749 vBar.setValue(vBar.getMaximum()); 750 } 751 }); 752 } 753 754 private void updateXImage(int inFrame) { 755 if (mcidasxDS == null || frameDisplay == null) return; 756 try { 757 McIdasFrame frm = mcidasxDS.getFrame(inFrame); 758 Image imageGIF = frm.getGIF(); 759 frameDisplay.setFrameImage(inFrame, imageGIF); 760 } catch (Exception e) { 761 System.out.println("updateXImage exception: " + e); 762 } 763 } 764 765 private void showXImage(int inFrame) { 766 if (frameDisplay == null) return; 767 try { 768 frameDisplay.showFrameNumber(inFrame); 769 } catch (Exception e) { 770 System.out.println("showXImage exception: " + e); 771 } 772 } 773 774 private void updateVImage() { 775 try { 776 getRequestProperties(); 777 resetData(); 778 } catch (Exception e) { 779 System.out.println("updateVImage exception: " + e); 780 } 781 } 782 783 public boolean init(DataChoice choice) 784 throws VisADException, RemoteException { 785 setShowProgressBar(false); 786 boolean ret = super.init(choice, false); 787 return ret; 788 } 789 790 /** 791 * This gets called when the control has received notification of a 792 * dataChange event. 793 * 794 * @throws RemoteException Java RMI problem 795 * @throws VisADException VisAD problem 796 */ 797 protected void resetData() throws VisADException, RemoteException { 798 // Do not attempt to load any data unless the checkbox is set... 799 if (!navigatedCbx.isSelected()) return; 800 801 super.resetData(); 802 803 if (frameComponentInfo.getResetProjection()) { 804 MapProjection mp = getDataProjection(); 805 if (mp != null) { 806 MapViewManager mvm = getMapViewManager(); 807 mvm.setMapProjection(mp, false); 808 } 809 } 810 } 811 812 /** 813 * Try my hand at creating a thread 814 */ 815 private class McIdasCommandLine implements Runnable { 816 private String line; 817 private boolean showprocess; 818 public McIdasCommandLine() { 819 this.line = ""; 820 this.showprocess = true; 821 } 822 public McIdasCommandLine(String line, boolean showprocess) { 823 this.line = line; 824 this.showprocess = showprocess; 825 } 826 public void run() { 827 notifyThreadStart(); 828 sendCommandLine(this.line, this.showprocess); 829 notifyThreadStop(); 830 } 831 } 832 833 /** 834 * Threaded sendCommandLine 835 * @param line 836 * @param showprocess 837 */ 838 private void sendCommandLineThread(String line, boolean showprocess) { 839 McIdasCommandLine mcCmdLine = new McIdasCommandLine(line, showprocess); 840 Thread t = new Thread(mcCmdLine); 841 t.start(); 842 } 843 844 private void notifyThreadStart() { 845 this.threadCount++; 846 notifyThreadCount(); 847 } 848 private void notifyThreadStop() { 849 this.threadCount--; 850 notifyThreadCount(); 851 } 852 private void notifyThreadCount() { 853 runningThreads.setText("Running: " + this.threadCount); 854 } 855 856}