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