001 /* 002 * $Id: StormTrackChart.java,v 1.1 2012/01/04 20:39:38 tommyj 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.cyclone; 032 033 import java.awt.BorderLayout; 034 import java.awt.Dimension; 035 import java.awt.Insets; 036 import java.awt.event.ActionEvent; 037 import java.awt.event.ActionListener; 038 import java.util.ArrayList; 039 import java.util.Hashtable; 040 import java.util.List; 041 import java.util.Vector; 042 043 import javax.swing.BorderFactory; 044 import javax.swing.JButton; 045 import javax.swing.JCheckBox; 046 import javax.swing.JComponent; 047 import javax.swing.JLabel; 048 import javax.swing.JList; 049 import javax.swing.JPanel; 050 import javax.swing.JScrollPane; 051 import javax.swing.ListSelectionModel; 052 import javax.swing.event.ListSelectionEvent; 053 import javax.swing.event.ListSelectionListener; 054 055 import ucar.unidata.data.storm.StormDataSource; 056 import ucar.unidata.data.storm.StormParam; 057 import ucar.unidata.data.storm.StormTrack; 058 import ucar.unidata.data.storm.StormTrackPoint; 059 import ucar.unidata.data.storm.Way; 060 import ucar.unidata.idv.control.chart.LineState; 061 import ucar.unidata.idv.control.chart.TimeSeriesChart; 062 import ucar.unidata.util.GuiUtils; 063 import ucar.unidata.util.Misc; 064 import ucar.unidata.util.Range; 065 import ucar.unidata.util.TwoFacedObject; 066 import visad.DateTime; 067 import visad.Real; 068 import visad.RealType; 069 import visad.Unit; 070 071 /** 072 * 073 * @author Unidata Development Team 074 * @version $Revision: 1.1 $ 075 */ 076 077 public class StormTrackChart { 078 079 /** _more_ */ 080 public static final int MODE_FORECASTTIME = 0; 081 082 /** _more_ */ 083 public static final int MODE_FORECASTHOUR = 1; 084 085 /** _more_ */ 086 private StormDisplayState stormDisplayState; 087 088 /** _more_ */ 089 private int mode; 090 091 /** _more_ */ 092 private TimeSeriesChart timeSeries; 093 094 /** _more_ */ 095 private JPanel chartLeft; 096 097 /** _more_ */ 098 private JPanel chartTop; 099 100 /** _more_ */ 101 private boolean madeChart = false; 102 103 /** _more_ */ 104 private List<DateTime> forecastTimes; 105 106 /** _more_ */ 107 private List<Integer> forecastHours; 108 109 /** _more_ */ 110 private List<StormParam> chartParams = new ArrayList<StormParam>(); 111 112 /** _more_ */ 113 private List<Way> chartWays = new ArrayList(); 114 115 /** _more_ */ 116 private boolean chartDifference = false; 117 118 /** _more_ */ 119 private JList chartTimeBox; 120 121 /** _more_ */ 122 private boolean ignoreChartTimeChanges = false; 123 124 /** _more_ */ 125 private JComponent contents; 126 127 /** _more_ */ 128 private String name; 129 130 /** 131 * _more_ 132 */ 133 public StormTrackChart() { 134 } 135 136 /** 137 * _more_ 138 * 139 * @param stormDisplayState 140 * _more_ 141 * @param name 142 * _more_ 143 * 144 */ 145 public StormTrackChart(StormDisplayState stormDisplayState, String name) { 146 this(stormDisplayState, name, MODE_FORECASTTIME); 147 } 148 149 /** 150 * _more_ 151 * 152 * @param stormDisplayState 153 * _more_ 154 * @param name 155 * _more_ 156 * @param mode 157 * _more_ 158 */ 159 public StormTrackChart(StormDisplayState stormDisplayState, String name, 160 int mode) { 161 this.stormDisplayState = stormDisplayState; 162 this.name = name; 163 this.mode = mode; 164 } 165 166 /** 167 * _more_ 168 * 169 * @return _more_ 170 */ 171 protected boolean isHourly() { 172 return mode == MODE_FORECASTHOUR; 173 } 174 175 /** 176 * _more_ 177 */ 178 public void deactivate() { 179 madeChart = false; 180 contents = null; 181 } 182 183 /** 184 * _more_ 185 * 186 * @return _more_ 187 */ 188 protected JComponent getContents() { 189 if (contents == null) { 190 contents = doMakeContents(); 191 } 192 return contents; 193 } 194 195 /** 196 * _more_ 197 * 198 * @return _more_ 199 */ 200 private JComponent doMakeContents() { 201 chartTop = new JPanel(new BorderLayout()); 202 chartLeft = new JPanel(new BorderLayout()); 203 JComponent chartComp = GuiUtils.leftCenter(chartLeft, GuiUtils 204 .topCenter(chartTop, getChart().getContents())); 205 return chartComp; 206 } 207 208 /** 209 * Get the chart 210 * 211 * @return The chart_ 212 */ 213 public TimeSeriesChart getChart() { 214 if (timeSeries == null) { 215 timeSeries = new TimeSeriesChart(stormDisplayState 216 .getStormTrackControl(), "Track Charts") { 217 protected void makeInitialChart() { 218 } 219 }; 220 // TODO make this work: 221 // timeSeries.setAlwaysShowFirstChart(false); 222 timeSeries.showAnimationTime(true); 223 timeSeries.setDateFormat("MM/dd HH:mm z"); 224 } 225 return timeSeries; 226 } 227 228 /** 229 * _more_ 230 * 231 * @param time 232 * _more_ 233 */ 234 protected void timeChanged(Real time) { 235 getChart().timeChanged(); 236 } 237 238 /** 239 * _more_ 240 * 241 * @return _more_ 242 */ 243 private List<DateTime> findForecastTimes() { 244 List<DateTime> forecastTimes = new ArrayList<DateTime>(); 245 Hashtable seenForecastTime = new Hashtable(); 246 for (StormTrack track : stormDisplayState.getTrackCollection() 247 .getTracks()) { 248 if (track.getWay().isObservation()) { 249 continue; 250 } 251 if (!chartWays.contains(track.getWay())) { 252 continue; 253 } 254 DateTime dttm = track.getStartTime(); 255 if (seenForecastTime.get(dttm) == null) { 256 seenForecastTime.put(dttm, dttm); 257 forecastTimes.add(dttm); 258 } 259 } 260 return (List<DateTime>) Misc.sort(forecastTimes); 261 } 262 263 /** 264 * _more_ 265 * 266 * @return _more_ 267 */ 268 private List<Integer> findForecastHours() { 269 List<Integer> forecastHours = new ArrayList<Integer>(); 270 Hashtable seenForecastHour = new Hashtable(); 271 Hashtable seen = new Hashtable(); 272 for (StormTrack track : stormDisplayState.getTrackCollection() 273 .getTracks()) { 274 if (track.getWay().isObservation()) { 275 continue; 276 } 277 if (!chartWays.contains(track.getWay())) { 278 continue; 279 } 280 for (StormTrackPoint stormTrackPoint : track.getTrackPoints()) { 281 Integer forecastHour = new Integer(stormTrackPoint 282 .getForecastHour()); 283 if (seenForecastHour.get(forecastHour) == null) { 284 seenForecastHour.put(forecastHour, forecastHour); 285 forecastHours.add(forecastHour); 286 } 287 } 288 } 289 return (List<Integer>) Misc.sort(forecastHours); 290 } 291 292 /** 293 * _more_ 294 */ 295 protected void createChart() { 296 297 if (madeChart) { 298 return; 299 } 300 madeChart = true; 301 final JCheckBox chartDiffCbx = new JCheckBox("Use Difference", 302 chartDifference); 303 chartDiffCbx.addActionListener(new ActionListener() { 304 public void actionPerformed(ActionEvent ae) { 305 chartDifference = chartDiffCbx.isSelected(); 306 updateChart(); 307 } 308 }); 309 310 chartTimeBox = new JList(); 311 chartTimeBox.setVisibleRowCount(3); 312 chartTimeBox 313 .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 314 chartTimeBox.addListSelectionListener(new ListSelectionListener() { 315 public void valueChanged(ListSelectionEvent e) { 316 if (ignoreChartTimeChanges) { 317 return; 318 } 319 320 updateChart(); 321 } 322 }); 323 324 List<StormParam> params = getStormTrackParams(); 325 326 Insets inset = new Insets(3, 7, 7, 0); 327 List chartComps = new ArrayList(); 328 329 List<Way> ways = Misc.sort(stormDisplayState.getTrackCollection() 330 .getWayList()); 331 List wayComps = new ArrayList(); 332 for (Way way : ways) { 333 final Way theWay = way; 334 if (way.isObservation() && !chartWays.contains(way)) { 335 chartWays.add(way); 336 } 337 final JCheckBox cbx = new JCheckBox(way.toString(), chartWays 338 .contains(theWay)); 339 cbx.addActionListener(new ActionListener() { 340 public void actionPerformed(ActionEvent ae) { 341 if (cbx.isSelected()) { 342 addChartWay(theWay); 343 } else { 344 removeChartWay(theWay); 345 } 346 } 347 }); 348 if (!way.isObservation()) { 349 wayComps.add(cbx); 350 } else { 351 wayComps.add(0, cbx); 352 } 353 } 354 355 chartComps.add(new JLabel(stormDisplayState.getStormTrackControl() 356 .getWaysName() 357 + ":")); 358 JComponent chartWayComp = GuiUtils.vbox(wayComps); 359 if (wayComps.size() > 6) { 360 chartWayComp = makeScroller(chartWayComp, 100, 150); 361 } 362 chartComps.add(GuiUtils.inset(chartWayComp, inset)); 363 chartComps.add(GuiUtils.lLabel((isHourly() ? "Forecast Hour:" 364 : "Forecast Time:"))); 365 JScrollPane sp = new JScrollPane(chartTimeBox); 366 chartComps.add(GuiUtils.inset(sp, inset)); 367 368 List paramComps = new ArrayList(); 369 for (StormParam param : params) { 370 // if (param.getIsChartParam() == false) { 371 // continue; 372 // } 373 final StormParam theParam = param; 374 boolean useChartParam = chartParams.contains(theParam); 375 final JCheckBox cbx = new JCheckBox(param.toString(), useChartParam); 376 cbx.addActionListener(new ActionListener() { 377 public void actionPerformed(ActionEvent ae) { 378 if (cbx.isSelected()) { 379 addChartParam(theParam); 380 } else { 381 removeChartParam(theParam); 382 } 383 } 384 }); 385 paramComps.add(cbx); 386 } 387 chartComps.add(new JLabel("Parameters:")); 388 JComponent paramComp = GuiUtils.vbox(paramComps); 389 if (paramComps.size() > 6) { 390 paramComp = makeScroller(paramComp, 100, 150); 391 } 392 chartComps.add(GuiUtils.inset(paramComp, inset)); 393 chartComps.add(chartDiffCbx); 394 395 JButton removeBtn = GuiUtils.makeButton("Remove Chart", this, 396 "removeChart"); 397 chartComps.add(GuiUtils.filler(5, 10)); 398 chartComps.add(removeBtn); 399 400 // JComponent top = GuiUtils.left(GuiUtils.hbox( 401 // GuiUtils.label("Forecast Time: ", chartTimeBox), 402 // chartDiffCbx)); 403 // top = GuiUtils.inset(top,5); 404 // chartTop.add(BorderLayout.NORTH, top); 405 JComponent left = GuiUtils.doLayout(chartComps, 1, GuiUtils.WT_N, 406 new double[] { 0, 1, 0, 1, 0 }); 407 chartLeft.add(BorderLayout.CENTER, GuiUtils.inset(left, 5)); 408 409 chartLeft.invalidate(); 410 chartLeft.validate(); 411 chartLeft.repaint(); 412 413 } 414 415 /** 416 * _more_ 417 * 418 * @return _more_ 419 */ 420 protected List getStormTrackParams() { 421 // Get the types from the first forecast track 422 List<StormParam> params = stormDisplayState.getStormChartParams(); 423 if ((params == null) || (params.size() == 0)) { 424 for (StormTrack track : stormDisplayState.getTrackCollection() 425 .getTracks()) { 426 if (track == null) { 427 continue; 428 } 429 if (!track.isObservation()) { 430 params = track.getParams(); 431 break; 432 } 433 } 434 435 // If we didn't get any from the forecast track use the obs track 436 if (params.size() == 0) { 437 StormTrack obsTrack = stormDisplayState.getTrackCollection() 438 .getObsTrack(); 439 if (obsTrack != null) { 440 params = obsTrack.getParams(); 441 } 442 } 443 } 444 return params; 445 446 } 447 448 /** 449 * _more_ 450 */ 451 public void removeChart() { 452 if (GuiUtils.askOkCancel("Remove Chart", 453 "Do you want to remove this chart?")) { 454 stormDisplayState.removeChart(this); 455 456 } 457 458 } 459 460 /** 461 * _more_ 462 * 463 * @param comp 464 * _more_ 465 * @param width 466 * _more_ 467 * @param height 468 * _more_ 469 * 470 * @return _more_ 471 */ 472 JScrollPane makeScroller(JComponent comp, int width, int height) { 473 JScrollPane scroller = GuiUtils.makeScrollPane(comp, width, height); 474 scroller.setBorder(BorderFactory.createLoweredBevelBorder()); 475 scroller.setPreferredSize(new Dimension(width, height)); 476 scroller.setMinimumSize(new Dimension(width, height)); 477 return scroller; 478 } 479 480 /** 481 * _more_ 482 * 483 * @param stormTrack 484 * _more_ 485 * @param param 486 * _more_ 487 * 488 * @return _more_ 489 */ 490 protected LineState makeLine(StormTrack stormTrack, StormParam param) { 491 List<Real> values = new ArrayList<Real>(); 492 List<DateTime> times = stormTrack.getTrackTimes(); 493 List<StormTrackPoint> trackPoints = stormTrack.getTrackPoints(); 494 double min = 0; 495 double max = 0; 496 Unit unit = null; 497 for (int pointIdx = 0; pointIdx < times.size(); pointIdx++) { 498 Real value = trackPoints.get(pointIdx).getAttribute(param); 499 if (value == null) { 500 continue; 501 } 502 if (unit == null) { 503 unit = ((RealType) value.getType()).getDefaultUnit(); 504 } 505 values.add(value); 506 double dvalue = value.getValue(); 507 // System.err.print(","+dvalue); 508 if ((pointIdx == 0) || (dvalue > max)) { 509 max = dvalue; 510 } 511 if ((pointIdx == 0) || (dvalue < min)) { 512 min = dvalue; 513 } 514 } 515 if (values.size() == 0) { 516 return null; 517 } 518 // System.err.println(""); 519 String paramLabel = param.toString(); 520 String label = stormTrack.getWay().toString(); // +":" + paramLabel; 521 LineState lineState = new LineState(); 522 lineState.setRangeIncludesZero(true); 523 if (stormTrack.getWay().isObservation()) { 524 lineState.setWidth(2); 525 } else { 526 lineState.setWidth(1); 527 } 528 lineState.setRange(new Range(min, max)); 529 lineState.setChartName(paramLabel); 530 lineState.setAxisLabel("[" + unit + "]"); 531 532 // System.err.println (param + " " + 533 // StormDataSource.TYPE_STORMCATEGORY); 534 if (Misc.equals(param, StormDataSource.PARAM_STORMCATEGORY)) { 535 // lineState.setShape(LineState.LINETYPE_BAR); 536 lineState.setLineType(LineState.LINETYPE_BAR); 537 lineState.setLineType(LineState.LINETYPE_AREA); 538 } else { 539 lineState.setLineType(LineState.LINETYPE_SHAPES_AND_LINES); 540 lineState.setShape(LineState.SHAPE_LARGEPOINT); 541 } 542 543 lineState.setColor(stormDisplayState.getWayDisplayState( 544 stormTrack.getWay()).getColor()); 545 lineState.setName(label); 546 lineState.setTrack(times, values); 547 return lineState; 548 549 } 550 551 /** 552 * _more_ 553 * 554 * 555 * @param param 556 * _more_ 557 */ 558 private void removeChartParam(StormParam param) { 559 while (chartParams.contains(param)) { 560 chartParams.remove(param); 561 } 562 updateChart(); 563 } 564 565 /** 566 * _more_ 567 * 568 * 569 * @param param 570 * _more_ 571 */ 572 private void addChartParam(StormParam param) { 573 if (!chartParams.contains(param)) { 574 chartParams.add(param); 575 } 576 updateChart(); 577 } 578 579 /** 580 * _more_ 581 * 582 * @param way 583 * _more_ 584 */ 585 private void removeChartWay(Way way) { 586 while (chartWays.contains(way)) { 587 chartWays.remove(way); 588 } 589 updateChart(); 590 } 591 592 /** 593 * _more_ 594 * 595 * @param way 596 * _more_ 597 */ 598 private void addChartWay(Way way) { 599 if (!chartWays.contains(way)) { 600 chartWays.add(way); 601 } 602 updateChart(); 603 } 604 605 /** 606 * _more_ 607 */ 608 private void getSelectedTimes() { 609 if (isHourly()) { 610 Object[] selects = chartTimeBox.getSelectedValues(); 611 if (forecastHours == null) { 612 forecastHours = new ArrayList(); 613 } 614 for (int i = 0; i < selects.length; i++) { 615 Object select = selects[i]; 616 TwoFacedObject tfo = (TwoFacedObject) select; 617 Integer hour = (Integer) tfo.getId(); 618 forecastHours.add(hour); 619 } 620 621 } else { 622 forecastTimes = (List<DateTime>) Misc.toList(chartTimeBox 623 .getSelectedValues()); 624 625 } 626 } 627 628 /** 629 * _more_ 630 */ 631 protected void updateChart() { 632 633 try { 634 if (!madeChart) { 635 createChart(); 636 } 637 ignoreChartTimeChanges = true; 638 639 if (isHourly()) { 640 List<Integer> fHours = findForecastHours(); 641 List<TwoFacedObject> tfos = new ArrayList<TwoFacedObject>(); 642 for (Integer i : fHours) { 643 tfos.add(new TwoFacedObject(i + "H", i)); 644 } 645 646 Object[] selected = chartTimeBox.getSelectedValues(); 647 chartTimeBox.setListData(new Vector(tfos)); 648 GuiUtils.setSelectedItems(chartTimeBox, Misc.toList(selected)); 649 650 if ((selected == null) && (tfos.size() > 0)) { 651 TwoFacedObject selected0 = tfos.get(0); 652 forecastHours.add((Integer) selected0.getId()); 653 } 654 655 // chartTimeBox.setSelectedItem(selected); 656 } else { 657 List<DateTime> fTimes = findForecastTimes(); 658 659 Object[] selected = chartTimeBox.getSelectedValues(); 660 661 chartTimeBox.setListData(new Vector(fTimes)); 662 GuiUtils.setSelectedItems(chartTimeBox, Misc.toList(selected)); 663 664 if ((selected == null) && (fTimes.size() > 0)) { 665 DateTime dt0 = fTimes.get(0); 666 forecastTimes.add(dt0); 667 } 668 669 // chartTimeBox.setSelectedItem(forecastTime); 670 } 671 ignoreChartTimeChanges = false; 672 getSelectedTimes(); 673 chartTimeBox.repaint(); 674 Hashtable<Way, List> wayToTracks = new Hashtable<Way, List>(); 675 for (Way way : chartWays) { 676 wayToTracks.put(way, new ArrayList<Way>()); 677 } 678 679 List<StormTrack> tracksToUse = new ArrayList<StormTrack>(); 680 for (StormTrack track : stormDisplayState.getTrackCollection() 681 .getTracks()) { 682 List trackList = wayToTracks.get(track.getWay()); 683 if (trackList == null) { 684 continue; 685 } 686 if (track.getWay().isObservation()) { 687 tracksToUse.add(track); 688 } else { 689 trackList.add(track); 690 } 691 } 692 693 StormTrack obsTrack = stormDisplayState.getTrackCollection() 694 .getObsTrack(); 695 696 if (isHourly()) { 697 for (Way way : chartWays) { 698 List<StormTrack> tracksFromWay = wayToTracks.get(way); 699 700 for (Integer fHour : forecastHours) { 701 List<StormTrackPoint> points = new ArrayList<StormTrackPoint>(); 702 for (StormTrack track : tracksFromWay) { 703 StormTrackPoint stp = track 704 .findPointWithForecastHour(fHour.intValue()); 705 if (stp != null) { 706 // TODO: What time do we use??? 707 points.add(stp); 708 } 709 710 } 711 if (points.size() > 0) { 712 points = (List<StormTrackPoint>) Misc.sort(points); 713 tracksToUse.add(new StormTrack(stormDisplayState 714 .getStormInfo(), way, points, null)); 715 } 716 } 717 } 718 719 } else { 720 for (Way way : chartWays) { 721 List<StormTrack> tracksFromWay = wayToTracks.get(way); 722 for (StormTrack track : tracksFromWay) { 723 for (DateTime fTime : forecastTimes) { 724 if (Misc.equals(fTime, track.getStartTime())) { 725 tracksToUse.add(track); 726 } 727 } 728 } 729 } 730 } 731 732 List<LineState> lines = new ArrayList<LineState>(); 733 734 for (StormParam param : chartParams) { 735 Hashtable seenWays = new Hashtable(); 736 List<LineState> linesForParam = new ArrayList<LineState>(); 737 for (StormTrack track : tracksToUse) { 738 LineState lineState = null; 739 if (chartDifference && param.getCanDoDifference()) { 740 if (track.getWay().isObservation()) { 741 continue; 742 } 743 track = StormDataSource.difference(obsTrack, track, 744 param); 745 if (track != null) { 746 lineState = makeLine(track, param); 747 } 748 } else { 749 lineState = makeLine(track, param); 750 } 751 if (lineState == null) { 752 continue; 753 } 754 // Only add it if there are values 755 if (lineState.getRange().getMin() == lineState.getRange() 756 .getMin()) { 757 if (seenWays.get(track.getWay()) != null) { 758 lineState.setVisibleInLegend(false); 759 } else { 760 seenWays.put(track.getWay(), ""); 761 } 762 763 linesForParam.add(lineState); 764 } 765 } 766 double max = Double.NEGATIVE_INFINITY; 767 double min = Double.POSITIVE_INFINITY; 768 ; 769 for (LineState lineState : linesForParam) { 770 Range r = lineState.getRange(); 771 min = Math.min(min, r.getMin()); 772 max = Math.max(max, r.getMax()); 773 } 774 // System.err.println(param + " min/max:" + min + "/" + max); 775 boolean first = true; 776 for (LineState lineState : linesForParam) { 777 lineState.setAxisVisible(first); 778 first = false; 779 lineState.setRange(new Range(min, max)); 780 } 781 lines.addAll(linesForParam); 782 } 783 getChart().setTracks(lines); 784 } catch (Exception exc) { 785 stormDisplayState.getStormTrackControl().logException( 786 "Updating chart", exc); 787 } 788 789 } 790 791 /** 792 * Set the ChartParams property. 793 * 794 * @param value 795 * The new value for ChartParams 796 */ 797 public void setChartParams(List<StormParam> value) { 798 chartParams = value; 799 } 800 801 /** 802 * Get the ChartParams property. 803 * 804 * @return The ChartParams 805 */ 806 public List<StormParam> getChartParams() { 807 return chartParams; 808 } 809 810 /** 811 * Set the ChartWays property. 812 * 813 * @param value 814 * The new value for ChartWays 815 */ 816 public void setChartWays(List<Way> value) { 817 chartWays = value; 818 } 819 820 /** 821 * Get the ChartWays property. 822 * 823 * @return The ChartWays 824 */ 825 public List<Way> getChartWays() { 826 return chartWays; 827 } 828 829 /** 830 * Set the ChartForecastTime property. 831 * 832 * @param value 833 * The new value for ChartForecastTime 834 */ 835 public void setForecastTime(DateTime value) { 836 forecastTimes = (List<DateTime>) Misc.newList(value); 837 } 838 839 /** 840 * _more_ 841 * 842 * @param value 843 * _more_ 844 */ 845 public void setForecastTimes(List<DateTime> value) { 846 forecastTimes = value; 847 } 848 849 /** 850 * _more_ 851 * 852 * @return _more_ 853 */ 854 public List<DateTime> getForecastTimes() { 855 return forecastTimes; 856 } 857 858 /** 859 * Set the ChartDifference property. 860 * 861 * @param value 862 * The new value for ChartDifference 863 */ 864 public void setChartDifference(boolean value) { 865 chartDifference = value; 866 } 867 868 /** 869 * Get the ChartDifference property. 870 * 871 * @return The ChartDifference 872 */ 873 public boolean getChartDifference() { 874 return chartDifference; 875 } 876 877 /** 878 * Set the Name property. 879 * 880 * @param value 881 * The new value for Name 882 */ 883 public void setName(String value) { 884 name = value; 885 } 886 887 /** 888 * Get the Name property. 889 * 890 * @return The Name 891 */ 892 public String getName() { 893 return name; 894 } 895 896 /** 897 * Set the StormDisplayState property. 898 * 899 * @param value 900 * The new value for StormDisplayState 901 */ 902 public void setStormDisplayState(StormDisplayState value) { 903 stormDisplayState = value; 904 } 905 906 /** 907 * Get the StormDisplayState property. 908 * 909 * @return The StormDisplayState 910 */ 911 public StormDisplayState getStormDisplayState() { 912 return stormDisplayState; 913 } 914 915 /** 916 * Set the Mode property. 917 * 918 * @param value 919 * The new value for Mode 920 */ 921 public void setMode(int value) { 922 mode = value; 923 } 924 925 /** 926 * Get the Mode property. 927 * 928 * @return The Mode 929 */ 930 public int getMode() { 931 return mode; 932 } 933 934 /** 935 * Set the ForecastHour property. 936 * 937 * @param value 938 * The new value for ForecastHour 939 */ 940 public void setForecastHour(int value) { 941 forecastHours = (List<Integer>) Misc.newList(new Integer(value)); 942 } 943 944 /** 945 * _more_ 946 * 947 * @param value 948 * _more_ 949 */ 950 public void setForecastHours(List<Integer> value) { 951 forecastHours = value; 952 } 953 954 /** 955 * _more_ 956 * 957 * @return _more_ 958 */ 959 public List<Integer> getForecastHours() { 960 return forecastHours; 961 } 962 }