001 package org.LiveGraph.settings; 002 003 import static org.LiveGraph.settings.SettingsEvent.*; 004 005 import java.awt.Color; 006 import java.io.FileInputStream; 007 import java.io.FileOutputStream; 008 import java.io.IOException; 009 import java.util.Properties; 010 011 import org.LiveGraph.LiveGraph; 012 import org.LiveGraph.events.Event; 013 014 import com.softnetConsult.utils.math.MathTools; 015 import com.softnetConsult.utils.string.StringTools; 016 017 /** 018 * Encapsulates settings concerned with the data graphs and the plot canvas. 019 * 020 * <p style="font-size:smaller;">This product includes software developed by the 021 * <strong>LiveGraph</strong> project and its contributors.<br /> 022 * (<a href="http://www.live-graph.org" target="_blank">http://www.live-graph.org</a>)<br /> 023 * Copyright (c) 2007-2008 G. Paperin.<br /> 024 * All rights reserved. 025 * </p> 026 * <p style="font-size:smaller;">File: GraphSettings.java</p> 027 * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or 028 * without modification, are permitted provided that the following terms and conditions are met: 029 * </p> 030 * <p style="font-size:smaller;">1. Redistributions of source code must retain the above 031 * acknowledgement of the LiveGraph project and its web-site, the above copyright notice, 032 * this list of conditions and the following disclaimer.<br /> 033 * 2. Redistributions in binary form must reproduce the above acknowledgement of the 034 * LiveGraph project and its web-site, the above copyright notice, this list of conditions 035 * and the following disclaimer in the documentation and/or other materials provided with 036 * the distribution.<br /> 037 * 3. All advertising materials mentioning features or use of this software or any derived 038 * software must display the following acknowledgement:<br /> 039 * <em>This product includes software developed by the LiveGraph project and its 040 * contributors.<br />(http://www.live-graph.org)</em><br /> 041 * 4. All advertising materials distributed in form of HTML pages or any other technology 042 * permitting active hyper-links that mention features or use of this software or any 043 * derived software must display the acknowledgment specified in condition 3 of this 044 * agreement, and in addition, include a visible and working hyper-link to the LiveGraph 045 * homepage (http://www.live-graph.org). 046 * </p> 047 * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 048 * OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 049 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 050 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 051 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 052 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 053 * </p> 054 * 055 * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>) 056 * @version {@value org.LiveGraph.LiveGraph#version} 057 */ 058 public class GraphSettings extends ObservableSettings { 059 060 /** 061 * Standard file extension. 062 */ 063 public static final String preferredFileExtension = ".lggs"; 064 065 /** 066 * Possible types for the vertical grid. 067 */ 068 public static enum VGridType { 069 /** 070 * No vertical grid. 071 */ 072 VGrid_None, 073 074 /** 075 * Vertical grid is based on dataset indices. 076 */ 077 VGrid_DSNumAligned, 078 079 /** 080 * Vertical grid is based on X data values. 081 */ 082 VGrid_XAUnitAligned 083 }; 084 085 /** 086 * Possible types for the horizontal grid. 087 */ 088 public static enum HGridType { 089 /** 090 * No horisontal grid. 091 */ 092 HGrid_None, 093 094 /** 095 * Horisontal grid is based on Y data values. 096 */ 097 HGrid_Simple 098 }; 099 100 /** 101 * Possible types for the x-axis. 102 */ 103 public static enum XAxisType { 104 /** 105 * Use dataset numbers as x-axis units. 106 */ 107 XAxis_DSNum, 108 109 /** 110 * Plot against a specified data series 111 * (use the values of a specified data series as x-axis values). 112 */ 113 XAxis_DataValSimple, 114 115 /** 116 * Plot against a specified data series transformed into the unit interval 117 * (use the values of a specified data series linearly transformed into the 118 * interval [0..1] as x-axis values). 119 */ 120 XAxis_DataValTrans0to1, 121 122 /** 123 * Plot against a specified data series scaled by a specified constant 124 * (use the values of a specified data series multiplied by a specified value as x-axis values). 125 */ 126 XAxis_DataValScaleBySetVal, 127 128 /** 129 * Plot against the logarithm of a specified data series to a specified base 130 * (use the values of logarithms of a specified data series taken to a specified base as x-axis values). 131 */ 132 XAxis_DataValLogToSetBase, 133 134 /** 135 * Plot against time 136 * (assume that the values of a specified data series represent seconds taken to a specified power 137 * of 10 (e.g. if {@code -3} is specified, the values represent milliseconds); plot against 138 * that axis while appropriately formatting the time (e.g. {@code hhh:mm:ss.xxx}). 139 */ 140 XAxis_DataValSecsToSetPower 141 }; 142 143 144 /** 145 * Bottom edge of the visible data area. 146 * Default value: {@code Double.NaN} ({@code Auto}). 147 */ 148 private double minY = Double.NaN; 149 150 /** 151 * Top edge of the visible data area. 152 * Default value: {@code Double.NaN} ({@code Auto}). 153 */ 154 private double maxY = Double.NaN; 155 156 /** 157 * Left edge of the visible data area. 158 * Default value: {@code Double.NaN} ({@code Auto}). 159 */ 160 private double minX = Double.NaN; 161 162 /** 163 * Right edge of the visible data area. 164 * Default value: {@code Double.NaN} ({@code Auto}). 165 */ 166 private double maxX = Double.NaN; 167 168 /** 169 * Type of the vertical grid. 170 * Default value: {@code VGridType.VGrid_None}. 171 */ 172 private VGridType vGridType = VGridType.VGrid_None; 173 174 /** 175 * Spacing of the vertical grid in data coordinates. 176 * Default value: {@code 50}. 177 */ 178 private double vGridSize = 50.0; 179 180 /** 181 * Color of the vertical grid. 182 * Default value: {@code #C0C0C0}. 183 */ 184 private Color vGridColour = new Color(Integer.parseInt("C0", 16), 185 Integer.parseInt("C0", 16), 186 Integer.parseInt("C0", 16)); 187 188 /** 189 * Type of the horisontal grid. 190 * Default value: {@code HGridType.HGrid_None}. 191 */ 192 private HGridType hGridType = HGridType.HGrid_None; 193 194 /** 195 * Spacing of the horisontal grid in data coordinates. 196 * Default value: {@code 50}. 197 */ 198 private double hGridSize = 50.0; 199 200 /** 201 * Color of the horisontal grid. 202 * Default value: {@code #C0C0C0}. 203 */ 204 private Color hGridColour = new Color(Integer.parseInt("C0", 16), 205 Integer.parseInt("C0", 16), 206 Integer.parseInt("C0", 16)); 207 208 /** 209 * Against what to plot the values. 210 * Default value: {@code XAxisType.XAxis_DSNum}. 211 */ 212 private XAxisType xAxisType = XAxisType.XAxis_DSNum; 213 214 /** 215 * Against which data series to plot (index). 216 * Default value: {@code 0}. 217 */ 218 private int xAxisSeriesIndex = 0; 219 220 /** 221 * Parameter for transformation of x-values. 222 * Default value: {@code 1}. 223 */ 224 private double xAxisParamValue = 1.0; 225 226 /** 227 * Whether to highlight data points as mouse is moved over the graph. 228 * Default value: {@code true}. 229 */ 230 private boolean highlightDataPoints = true; 231 232 233 /** 234 * Creates a new graph settings object with the default settings. 235 */ 236 public GraphSettings() { 237 super(); 238 checkDisableHighlightingForOldJava(); 239 } 240 241 /** 242 * Creates a new graph settings object and loads the settings from the specified file. 243 * 244 * @param fileName File to load the settigs from. 245 */ 246 public GraphSettings(String fileName) { 247 this(); 248 load(fileName); 249 } 250 251 /** 252 * Loads the settings from the specified file. 253 * 254 * @param fileName File to load the settigs from. 255 * @return {@code true} if the settings were loaded, {@code false} if an exception occured. 256 */ 257 public boolean load(String fileName) { 258 259 // Check observers: 260 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_Load, fileName); 261 if (null == actionEvent) 262 return false; 263 264 // Used for loading: 265 Properties values = new Properties(); 266 267 // Read from file: 268 try { 269 FileInputStream in = new FileInputStream(fileName); 270 try { 271 values.loadFromXML(in); 272 } finally { 273 in.close(); 274 } 275 } catch(IOException e) { 276 e.printStackTrace(); 277 return false; 278 } 279 280 // Parse values and set: 281 282 String s = values.getProperty("MinY", "Auto"); 283 if ("Auto".equalsIgnoreCase(s)) { 284 minY = Double.NaN; 285 } else { 286 try { 287 minY = StringTools.parseDouble(s); 288 } catch (NumberFormatException e) { 289 minY = Double.parseDouble(s); 290 } 291 } 292 293 294 s = values.getProperty("MaxY", "Auto"); 295 if ("Auto".equalsIgnoreCase(s)) { 296 maxY = Double.NaN; 297 } else { 298 try { 299 maxY = StringTools.parseDouble(s); 300 } catch (NumberFormatException e) { 301 maxY = Double.parseDouble(s); 302 } 303 } 304 305 306 s = values.getProperty("MinX", "Auto"); 307 if ("Auto".equalsIgnoreCase(s)) { 308 minX = Double.NaN; 309 } else { 310 try { 311 minX = StringTools.parseDouble(s); 312 } catch (NumberFormatException e) { 313 minX = Double.parseDouble(s); 314 } 315 } 316 317 318 s = values.getProperty("MaxX", "Auto"); 319 if ("Auto".equalsIgnoreCase(s)) { 320 maxX = Double.NaN; 321 } else { 322 try { 323 maxX = StringTools.parseDouble(s); 324 } catch (NumberFormatException e) { 325 maxX = Double.parseDouble(s); 326 } 327 } 328 329 330 s = values.getProperty("VGridType", "VGrid_None"); 331 vGridType = VGridType.VGrid_None; 332 for (VGridType t : VGridType.values()) { 333 if (t.name().equalsIgnoreCase(s)) { 334 vGridType = t; 335 break; 336 } 337 } 338 339 340 s = values.getProperty("VGridSize", "50"); 341 try { 342 vGridSize = StringTools.parseDouble(s); 343 } catch (NumberFormatException e) { 344 vGridSize = Double.parseDouble(s); 345 } 346 if (Double.isNaN(vGridSize) || Double.isInfinite(vGridSize) || 0.0 > vGridSize) 347 vGridSize = 0.0; 348 349 350 s = values.getProperty("VGridColour", "C0C0C0"); 351 int r, g, b; 352 try { r = Integer.parseInt(s.substring(0, 2), 16); } catch(NumberFormatException e) { r = 0; } 353 try { g = Integer.parseInt(s.substring(2, 4), 16); } catch(NumberFormatException e) { g = 0; } 354 try { b = Integer.parseInt(s.substring(4, 6), 16); } catch(NumberFormatException e) { b = 0; } 355 vGridColour = new Color(r, g, b); 356 357 358 s = values.getProperty("HGridType", "HGrid_None"); 359 hGridType = HGridType.HGrid_None; 360 for (HGridType t : HGridType.values()) { 361 if (t.name().equalsIgnoreCase(s)) { 362 hGridType = t; 363 break; 364 } 365 } 366 367 368 s = values.getProperty("HGridSize", "50"); 369 try { 370 hGridSize = StringTools.parseDouble(s); 371 } catch (NumberFormatException e) { 372 hGridSize = Double.parseDouble(s); 373 } 374 if (Double.isNaN(hGridSize) || Double.isInfinite(hGridSize) || 0.0 > hGridSize) 375 hGridSize = 0.0; 376 377 378 s = values.getProperty("HGridColour", "C0C0C0"); 379 try { r = Integer.parseInt(s.substring(0, 2), 16); } catch(NumberFormatException e) { r = 0; } 380 try { g = Integer.parseInt(s.substring(2, 4), 16); } catch(NumberFormatException e) { g = 0; } 381 try { b = Integer.parseInt(s.substring(4, 6), 16); } catch(NumberFormatException e) { b = 0; } 382 hGridColour = new Color(r, g, b); 383 384 385 s = values.getProperty("XAxisType", "XAxis_DSNum"); 386 xAxisType = XAxisType.XAxis_DSNum; 387 for (XAxisType t : XAxisType.values()) { 388 if (t.name().equalsIgnoreCase(s)) { 389 xAxisType = t; 390 break; 391 } 392 } 393 if (s.equalsIgnoreCase("XAxis_DataValScaledSet")) // Support ver 1.1.2 and prev: 394 xAxisType = XAxisType.XAxis_DataValScaleBySetVal; 395 396 397 s = values.getProperty("XAxisSeriesIndex", "0"); 398 xAxisSeriesIndex = Integer.parseInt(values.getProperty("XAxisSeriesIndex")); 399 if (0 > xAxisSeriesIndex) 400 xAxisSeriesIndex = 0; 401 402 403 s = values.getProperty("XAxisParamValue"); 404 if (null == s) // Compatibility with version 1.1.2 and before: 405 values.getProperty("XAxisScaleValue"); 406 if (null == s) 407 s = "1"; 408 try { 409 xAxisParamValue = StringTools.parseDouble(s); 410 } catch (NumberFormatException e) { 411 xAxisParamValue = Double.parseDouble(s); 412 } 413 if (Double.isNaN(xAxisParamValue) || Double.isInfinite(xAxisParamValue)) 414 xAxisParamValue = 1.0; 415 xAxisParamValue = ensureGoodXAxisParameter(xAxisType, xAxisParamValue); 416 417 418 s = values.getProperty("HighlightDataPoints", "1"); 419 highlightDataPoints = "1".equalsIgnoreCase(s); 420 if (values.containsKey("SavedWithIncompatibleJavaVersion") 421 && "1".equalsIgnoreCase(values.getProperty("SavedWithIncompatibleJavaVersion")) 422 && !highlightDataPoints 423 && LiveGraph.application().runsCorrectJavaVersion()) { 424 highlightDataPoints = true; 425 } 426 checkDisableHighlightingForOldJava(); 427 428 429 notifyObservers(actionEvent); 430 return true; 431 } 432 433 /** 434 * Saves the settings to a specified file. 435 * 436 * @param fileName The file to save the settings to. 437 * @return {@code true} if the settings were saved, {@code false} if an exception occured. 438 */ 439 public boolean save(String fileName) { 440 441 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_Save, fileName); 442 if (null == actionEvent) 443 return false; 444 445 Properties values = new Properties(); 446 447 if(!LiveGraph.application().runsCorrectJavaVersion()) 448 values.setProperty("SavedWithIncompatibleJavaVersion", "1"); 449 450 values.setProperty("MinY", Double.isNaN(getMinY()) ? "Auto" : StringTools.toString(getMinY())); 451 values.setProperty("MaxY", Double.isNaN(getMaxY()) ? "Auto" : StringTools.toString(getMaxY())); 452 values.setProperty("MinX", Double.isNaN(getMinX()) ? "Auto" : StringTools.toString(getMinX())); 453 values.setProperty("MaxX", Double.isNaN(getMaxX()) ? "Auto" : StringTools.toString(getMaxX())); 454 455 values.setProperty("VGridType", getVGridType().name()); 456 values.setProperty("VGridSize", StringTools.toString(getVGridSize())); 457 values.setProperty("VGridColour", String.format("%02x%02x%02x", 458 getVGridColour().getRed(), 459 getVGridColour().getGreen(), 460 getVGridColour().getBlue())); 461 462 values.setProperty("HGridType", getHGridType().name()); 463 values.setProperty("HGridSize", StringTools.toString(getHGridSize())); 464 values.setProperty("HGridColour", String.format("%02x%02x%02x", 465 getHGridColour().getRed(), 466 getHGridColour().getGreen(), 467 getHGridColour().getBlue())); 468 469 values.setProperty("XAxisType", getXAxisType().name()); 470 values.setProperty("XAxisSeriesIndex", Integer.toString(getXAxisSeriesIndex())); 471 values.setProperty("XAxisParamValue", StringTools.toString(getXAxisParamValue())); 472 473 values.setProperty("HighlightDataPoints", getHighlightDataPoints() ? "1" : "0"); 474 475 try { 476 477 FileOutputStream out = new FileOutputStream(fileName); 478 try { 479 values.storeToXML(out, "LiveGraph version " + LiveGraph.version + ". GraphSettings."); 480 } finally { 481 out.close(); 482 } 483 484 notifyObservers(actionEvent); 485 return true; 486 487 } catch(IOException e) { 488 e.printStackTrace(); 489 return false; 490 } 491 } 492 493 /** 494 * Gets the minimum Y value for the plot viewport. 495 * 496 * @return The minimum value along the Y axis for the graph view 497 * or {@code java.lang.Double.NaN} if the current global minimum of all data series 498 * should be used instead. 499 */ 500 public double getMinY() { 501 return minY; 502 } 503 504 /** 505 * Sets the minimum Y value for the plot viewport. 506 * 507 * @param v The minimum value along the Y axis for the graph view 508 * or {@code java.lang.Double.NaN} if the global minimum of all data series 509 * should be used at all times. 510 */ 511 public void setMinY(double v) { 512 513 if (v == getMinY()) 514 return; 515 516 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_MinY, v); 517 if (null == actionEvent) 518 return; 519 520 minY = v; 521 notifyObservers(actionEvent); 522 } 523 524 /** 525 * Gets the maximum Y value for the plot viewport. 526 * 527 * @return The maximum value along the Y axis for the graph view 528 * or {@code java.lang.Double.NaN} if the current global maximum of all data series 529 * should be used instead. 530 */ 531 public double getMaxY() { 532 return maxY; 533 } 534 535 /** 536 * Sets the maximum Y value for the plot viewport. 537 * 538 * @param v The maximum value along the Y axis for the graph view 539 * or {@code java.lang.Double.NaN} if the global maximum of all data series 540 * should be used at all times. 541 */ 542 public void setMaxY(double v) { 543 544 if (v == getMaxY()) 545 return; 546 547 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_MaxY, v); 548 if (null == actionEvent) 549 return; 550 551 maxY = v; 552 notifyObservers(actionEvent); 553 } 554 555 /** 556 * Gets the minimum X value for the plot viewport. 557 * 558 * @return The minimum value along the X axis for the graph view 559 * or {@code java.lang.Double.NaN} if the currently smallest X value of all data series 560 * should be used instead. 561 */ 562 public double getMinX() { 563 return minX; 564 } 565 566 /** 567 * Sets the minimum X value for the plot viewport. 568 * 569 * @param v The minimum value along the X axis for the graph view 570 * or {@code java.lang.Double.NaN} if the smallest X value of all data series 571 * should be used at all times. 572 */ 573 public void setMinX(double v) { 574 575 if (v == getMinX()) 576 return; 577 578 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_MinX, v); 579 if (null == actionEvent) 580 return; 581 582 minX = v; 583 notifyObservers(actionEvent); 584 } 585 586 /** 587 * Gets the maximum X value for the plot viewport. 588 * 589 * @return The maximum value along the X axis for the graph view 590 * or {@code java.lang.Double.NaN} if the currently largest X value of all data series 591 * should be used instead. 592 */ 593 public double getMaxX() { 594 return maxX; 595 } 596 597 /** 598 * Sets the maximum X value for the plot viewport. 599 * 600 * @param v The maximum value along the X axis for the graph view 601 * or {@code java.lang.Double.NaN} if the largest X value of all data series 602 * should be used at all times. 603 */ 604 public void setMaxX(double v) { 605 606 if (v == getMaxX()) 607 return; 608 609 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_MaxX, v); 610 if (null == actionEvent) 611 return; 612 613 maxX = v; 614 notifyObservers(actionEvent); 615 } 616 617 /** 618 * Sets the vertical grid type. 619 * 620 * @return The vertical grid type. 621 */ 622 public VGridType getVGridType() { 623 return vGridType; 624 } 625 626 /** 627 * Gets the vertical grid type. 628 * 629 * @param v The vertical grid type. 630 */ 631 public void setVGridType(VGridType v) { 632 633 if (null == v) 634 v = VGridType.VGrid_None; 635 636 if (v == getVGridType()) 637 return; 638 639 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_VGridType, v); 640 if (null == actionEvent) 641 return; 642 643 vGridType = v; 644 notifyObservers(actionEvent); 645 } 646 647 /** 648 * Gets the interval between the vertical grid bars. 649 * 650 * @return The interval between the vertical grid bars. 651 */ 652 public double getVGridSize() { 653 return vGridSize; 654 } 655 656 /** 657 * Sets the interval between the vertical grid bars. 658 * 659 * @param val The interval between the vertical grid bars. 660 */ 661 public void setVGridSize(double val) { 662 663 if (Double.isNaN(val) || Double.isInfinite(val) || 0.0 > val) 664 val = 0.0; 665 666 if (val == getVGridSize()) 667 return; 668 669 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_VGridSize, val); 670 if (null == actionEvent) 671 return; 672 673 674 vGridSize = val; 675 notifyObservers(actionEvent); 676 } 677 678 /** 679 * Gets the colour to use for drawing the vertical grid bars. 680 * 681 * @return The colour to use for drawing the vertical grid bars. 682 */ 683 public Color getVGridColour() { 684 return vGridColour; 685 } 686 687 /** 688 * Sets the colour to use for drawing the vertical grid bars. 689 * @param c The colour to use for drawing the vertical grid bars. 690 */ 691 public void setVGridColour(Color c) { 692 693 if (null == c) 694 c = new Color(Integer.parseInt("C0", 16), Integer.parseInt("C0", 16), Integer.parseInt("C0", 16)); 695 696 if (c == getVGridColour()) 697 return; 698 699 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_VGridColour, c); 700 if (null == actionEvent) 701 return; 702 703 vGridColour = c; 704 notifyObservers(actionEvent); 705 } 706 707 /** 708 * Gets the horizontal grid type. 709 * @return The horizontal grid type. 710 */ 711 public HGridType getHGridType() { 712 return hGridType; 713 } 714 715 /** 716 * Sets the horizontal grid type. 717 * @param v The horizontal grid type. 718 */ 719 public void setHGridType(HGridType v) { 720 721 if (null == v) 722 v = HGridType.HGrid_None; 723 724 if (v == getHGridType()) 725 return; 726 727 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_HGridType, v); 728 if (null == actionEvent) 729 return; 730 731 hGridType = v; 732 notifyObservers(actionEvent); 733 } 734 735 /** 736 * Gets the interval between the horizontal grib bars. 737 * 738 * @return The interval between the horizontal grib bars. 739 */ 740 public double getHGridSize() { 741 return hGridSize; 742 } 743 744 /** 745 * Sets the interval between the horizontal grib bars. 746 * @param val The interval between the horizontal grib bars. 747 */ 748 public void setHGridSize(double val) { 749 750 if (Double.isNaN(val) || Double.isInfinite(val) || 0.0 > val) 751 val = 0.0; 752 753 if (val == getHGridSize()) 754 return; 755 756 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_HGridSize, val); 757 if (null == actionEvent) 758 return; 759 760 hGridSize = val; 761 notifyObservers(actionEvent); 762 } 763 764 765 /** 766 * Gets the colour for drawing the horizontal grid bars. 767 * 768 * @return The colour for drawing the horizontal grid bars. 769 */ 770 public Color getHGridColour() { 771 return hGridColour; 772 } 773 774 /** 775 * Sets the colour for drawing the horizontal grid bars. 776 * 777 * @param c The colour for drawing the horizontal grid bars. 778 */ 779 public void setHGridColour(Color c) { 780 781 if (null == c) 782 c = new Color(Integer.parseInt("C0", 16), Integer.parseInt("C0", 16), Integer.parseInt("C0", 16)); 783 784 if (c == getHGridColour()) 785 return; 786 787 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_HGridColour, c); 788 if (null == actionEvent) 789 return; 790 791 hGridColour = c; 792 notifyObservers(actionEvent); 793 } 794 795 /** 796 * Gets the type for the x-axis. 797 * 798 * @return The type for the x-axis. 799 */ 800 public XAxisType getXAxisType() { 801 return xAxisType; 802 } 803 804 /** 805 * Sets the type for the x-axis. 806 * 807 * @param v The type for the x-axis. 808 */ 809 public void setXAxisType(XAxisType v) { 810 811 if (null == v) 812 v = XAxisType.XAxis_DSNum; 813 814 if (v == getXAxisType()) 815 return; 816 817 double p = getXAxisParamValue(); 818 double np = ensureGoodXAxisParameter(v, p); 819 820 int xAxisSerInd = getXAxisSeriesIndex(); 821 822 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_XAxisType, false, xAxisSerInd, np, v); 823 if (null == actionEvent) 824 return; 825 826 if (p != np && null == checkObservers(GS_XAxisParamValue, false, xAxisSerInd, np, v)) 827 return; 828 829 xAxisType = v; 830 831 if (p != np) 832 setXAxisParamValue(np); 833 834 notifyObservers(actionEvent); 835 } 836 837 /** 838 * Gets the index of the data series to use as the x-axis. 839 * 840 * @return The index of the data series to use as the x-axis. 841 */ 842 public int getXAxisSeriesIndex() { 843 return xAxisSeriesIndex; 844 } 845 846 /** 847 * Sets the index of the data series to use as the x-axis. 848 * 849 * @param val The index of the data series to use as the x-axis. 850 */ 851 public void setXAxisSeriesIndex(int val) { 852 853 if (0 > val) 854 val = 0; 855 856 if (val == getXAxisSeriesIndex()) 857 return; 858 859 double axisParam = getXAxisParamValue(); 860 XAxisType axisType = getXAxisType(); 861 862 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_XAxisSeriesIndex, 863 false, val, axisParam, axisType); 864 if (null == actionEvent) 865 return; 866 867 xAxisSeriesIndex = val; 868 notifyObservers(actionEvent); 869 } 870 871 /** 872 * Gets the x-axis transformation parameter. 873 * 874 * @return The x-axis transformation parameter. 875 */ 876 public double getXAxisParamValue() { 877 return xAxisParamValue; 878 } 879 880 /** 881 * Sets x-axis transformation parameter. 882 * 883 * @param val x-axis transformation parameter. 884 */ 885 public void setXAxisParamValue(double val) { 886 887 if (Double.isNaN(val) || Double.isInfinite(val)) 888 val = 1.0; 889 890 if (val == getXAxisParamValue()) 891 return; 892 893 XAxisType axisType = getXAxisType(); 894 895 val = ensureGoodXAxisParameter(axisType, val); 896 897 int xAxisSeriesIndex = getXAxisSeriesIndex(); 898 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_XAxisParamValue, 899 false, xAxisSeriesIndex, val, axisType); 900 if (null == actionEvent) 901 return; 902 903 xAxisParamValue = val; 904 notifyObservers(actionEvent); 905 } 906 907 /** 908 * Gets whether the data points in the vicinity of the mouse cursor should be highlighted. 909 * (Note, this is a hidden setting and cannot be changes via the GUI.) 910 * 911 * @return {@code true} if the data points in the vicinity of the mouse cursor should be highlighted, 912 * {@code false} otherwise. 913 */ 914 public boolean getHighlightDataPoints() { 915 return highlightDataPoints; 916 } 917 918 /** 919 * Gets whether the data points in the vicinity of the mouse cursor should be highlighted. 920 * (Note, this is a hidden setting and cannot be changes via the GUI.) 921 * 922 * @param v {@code true} if the data points in the vicinity of the mouse cursor are to be highlighted, 923 * {@code false} otherwise. 924 */ 925 public void setHighlightDataPoints(boolean v) { 926 927 if (v == getHighlightDataPoints()) 928 return; 929 930 Event<? extends SettingsEvent> actionEvent = checkObservers(GS_HighlightDataPoints, v); 931 if (null == actionEvent) 932 return; 933 934 boolean prev = highlightDataPoints; 935 highlightDataPoints = v; 936 checkDisableHighlightingForOldJava(); 937 938 if (prev != highlightDataPoints) 939 notifyObservers(actionEvent); 940 } 941 942 /** 943 * If the Java version is too old, data point highlighting is disabled. 944 */ 945 private void checkDisableHighlightingForOldJava() { 946 if (!LiveGraph.application().runsCorrectJavaVersion()) 947 highlightDataPoints = false; 948 } 949 950 /** 951 * Ensure that the transformation parameter has a legal value for the given 952 * x-axis type. The transformation parameter must be a real number. In addition, 953 * if the x-axis type is {@code XAxis_DataValLogToSetBase}, it must be 954 * non-negative and not 1. 955 * 956 * @param xAxisType The x-axis type for which to verify the parameter. 957 * @param parameter The transfom parameter to check. 958 * @return The corrected transform parameter. 959 */ 960 private double ensureGoodXAxisParameter(XAxisType xAxisType, double parameter) { 961 962 if (Double.isInfinite(parameter)) 963 parameter = (parameter > 0. ? 1. : -1.); 964 965 if (Double.isNaN(parameter)) 966 parameter = 0.; 967 968 if (xAxisType == XAxisType.XAxis_DataValLogToSetBase) { 969 970 double d = MathTools.log(parameter, 1.); 971 if (Double.isNaN(d) || Double.isInfinite(d)) { 972 973 if (0 > parameter) 974 parameter = -parameter; 975 if (1. == parameter) 976 parameter = 0.; 977 } 978 } 979 980 return parameter; 981 } 982 983 } // public class GraphSettings