001 package org.LiveGraph.settings; 002 003 import java.awt.Color; 004 import java.io.FileInputStream; 005 import java.io.FileOutputStream; 006 import java.io.IOException; 007 import java.util.Properties; 008 009 import org.LiveGraph.LiveGraph; 010 011 /** 012 * Encapsulates settings concerned with the data graphs and the plot canvas. 013 * 014 * <p style="font-size:smaller;">This product includes software developed by the 015 * <strong>LiveGraph</strong> project and its contributors.<br /> 016 * (<a href="http://www.live-graph.org" target="_blank">http://www.live-graph.org</a>)<br /> 017 * Copyright (c) 2007 G. Paperin.<br /> 018 * All rights reserved. 019 * </p> 020 * <p style="font-size:smaller;">File: GraphSettings.java</p> 021 * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or 022 * without modification, are permitted provided that the following terms and conditions are met: 023 * </p> 024 * <p style="font-size:smaller;">1. Redistributions of source code must retain the above 025 * acknowledgement of the LiveGraph project and its web-site, the above copyright notice, 026 * this list of conditions and the following disclaimer.<br /> 027 * 2. Redistributions in binary form must reproduce the above acknowledgement of the 028 * LiveGraph project and its web-site, the above copyright notice, this list of conditions 029 * and the following disclaimer in the documentation and/or other materials provided with 030 * the distribution.<br /> 031 * 3. All advertising materials mentioning features or use of this software or any derived 032 * software must display the following acknowledgement:<br /> 033 * <em>This product includes software developed by the LiveGraph project and its 034 * contributors.<br />(http://www.live-graph.org)</em><br /> 035 * 4. All advertising materials distributed in form of HTML pages or any other technology 036 * permitting active hyper-links that mention features or use of this software or any 037 * derived software must display the acknowledgment specified in condition 3 of this 038 * agreement, and in addition, include a visible and working hyper-link to the LiveGraph 039 * homepage (http://www.live-graph.org). 040 * </p> 041 * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 042 * OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 043 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 044 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 045 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 046 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 047 * </p> 048 * 049 * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>) 050 * @version {@value org.LiveGraph.LiveGraph#version} 051 */ 052 public class GraphSettings extends ObservableSettings { 053 054 /** 055 * Standard file extension. 056 */ 057 public static final String preferredFileExtension = ".lggs"; 058 059 /** 060 * Possible types for the vertical grid. 061 */ 062 public static enum VGridType { VGrid_None, VGrid_DSNumAligned, VGrid_XAUnitAligned }; 063 064 /** 065 * Possible types for the horizontal grid. 066 */ 067 public static enum HGridType { HGrid_None, HGrid_Simple }; 068 069 /** 070 * Possible types for the x-axis. 071 */ 072 public static enum XAxisType { XAxis_DSNum, XAxis_DataValSimple, XAxis_DataValTrans0to1, XAxis_DataValScaledSet }; 073 074 /** 075 * Default settings. 076 */ 077 private static final Properties defaultValues = new Properties(); 078 static { 079 defaultValues.setProperty("MinY", "Auto"); 080 defaultValues.setProperty("MaxY", "Auto"); 081 defaultValues.setProperty("MinX", "Auto"); 082 defaultValues.setProperty("MaxX", "Auto"); 083 defaultValues.setProperty("VGridType", "VGrid_None"); 084 defaultValues.setProperty("VGridSize", "50"); 085 defaultValues.setProperty("VGridColour", "C0C0C0"); 086 defaultValues.setProperty("HGridType", "HGrid_None"); 087 defaultValues.setProperty("HGridSize", "50"); 088 defaultValues.setProperty("HGridColour", "C0C0C0"); 089 defaultValues.setProperty("XAxisType", "XAxis_DSNum"); 090 defaultValues.setProperty("XAxisSeriesIndex", "0"); 091 defaultValues.setProperty("XAxisScaleValue", "100"); 092 defaultValues.setProperty("HighlightDataPoints", "1"); 093 } 094 095 /** 096 * Holds the current graph settings. 097 */ 098 private Properties values = null; 099 100 /** 101 * Creates a new graph settings object with the default settings. 102 */ 103 public GraphSettings() { 104 super(); 105 values = new Properties(); 106 values.putAll(defaultValues); 107 checkDisableHighlightingForOldJava(); 108 } 109 110 /** 111 * Creates a new graph settings object and loads the settings from the specified file. 112 * 113 * @param fileName File to load the settigs from. 114 */ 115 public GraphSettings(String fileName) { 116 this(); 117 load(fileName); 118 } 119 120 /** 121 * Loads the settings from the specified file. 122 * 123 * @param fileName File to load the settigs from. 124 * @return {@code true} if the settings were loaded, {@code false} if an exception occured. 125 */ 126 public boolean load(String fileName) { 127 try { 128 FileInputStream in = new FileInputStream(fileName); 129 try { 130 values.loadFromXML(in); 131 132 if (values.containsKey("SavedWithIncompatibleJavaVersion") 133 && "1".equals(values.getProperty("SavedWithIncompatibleJavaVersion")) 134 && !getHighlightDataPoints() 135 && LiveGraph.application().runsCorrectJavaVersion()) { 136 values.setProperty("HighlightDataPoints", "1"); 137 } 138 139 checkDisableHighlightingForOldJava(); 140 notifyObservers("load"); 141 } finally { in.close(); } 142 return true; 143 } catch(IOException e) { 144 e.printStackTrace(); 145 return false; 146 } 147 } 148 149 /** 150 * Saves the settings to a specified file. 151 * 152 * @param fileName The file to save the settings to. 153 * @return {@code true} if the settings were saved, {@code false} if an exception occured. 154 */ 155 public boolean save(String fileName) { 156 157 if(LiveGraph.application().runsCorrectJavaVersion()) 158 values.remove("SavedWithIncompatibleJavaVersion"); 159 else 160 values.setProperty("SavedWithIncompatibleJavaVersion", "1"); 161 162 try { 163 FileOutputStream out = new FileOutputStream(fileName); 164 try { values.storeToXML(out, "LiveGraph version " + LiveGraph.version + ". GraphSettings."); } 165 finally { out.close(); } 166 return true; 167 } catch(IOException e) { 168 e.printStackTrace(); 169 return false; 170 } 171 } 172 173 /** 174 * Gets the minimum Y value for the plot viewport. 175 * 176 * @return The minimum value along the Y axis for the graph view 177 * or {@code java.lang.Double.NaN} if the current global minimum of all data series 178 * should be used instead. 179 */ 180 public double getMinY() { 181 if ("Auto".equalsIgnoreCase(values.getProperty("MinY"))) 182 return Double.NaN; 183 else 184 return Double.parseDouble(values.getProperty("MinY")); 185 } 186 187 /** 188 * Sets the minimum Y value for the plot viewport. 189 * 190 * @param v The minimum value along the Y axis for the graph view 191 * or {@code java.lang.Double.NaN} if the global minimum of all data series 192 * should be used at all times. 193 */ 194 public void setMinY(double v) { 195 if (Double.isNaN(v)) 196 values.setProperty("MinY", "Auto"); 197 else 198 values.setProperty("MinY", Double.toString(v)); 199 notifyObservers("MinY"); 200 } 201 202 /** 203 * Gets the maximum Y value for the plot viewport. 204 * 205 * @return The maximum value along the Y axis for the graph view 206 * or {@code java.lang.Double.NaN} if the current global maximum of all data series 207 * should be used instead. 208 */ 209 public double getMaxY() { 210 if ("Auto".equalsIgnoreCase(values.getProperty("MaxY"))) 211 return Double.NaN; 212 else 213 return Double.parseDouble(values.getProperty("MaxY")); 214 } 215 216 /** 217 * Sets the maximum Y value for the plot viewport. 218 * 219 * @param v The maximum value along the Y axis for the graph view 220 * or {@code java.lang.Double.NaN} if the global maximum of all data series 221 * should be used at all times. 222 */ 223 public void setMaxY(double v) { 224 if (Double.isNaN(v)) 225 values.setProperty("MaxY", "Auto"); 226 else 227 values.setProperty("MaxY", Double.toString(v)); 228 notifyObservers("MaxY"); 229 } 230 231 /** 232 * Gets the minimum X value for the plot viewport. 233 * 234 * @return The minimum value along the X axis for the graph view 235 * or {@code java.lang.Double.NaN} if the currently smallest X value of all data series 236 * should be used instead. 237 */ 238 public double getMinX() { 239 if ("Auto".equalsIgnoreCase(values.getProperty("MinX"))) 240 return Double.NaN; 241 else 242 return Double.parseDouble(values.getProperty("MinX")); 243 } 244 245 /** 246 * Sets the minimum X value for the plot viewport. 247 * 248 * @param v The minimum value along the X axis for the graph view 249 * or {@code java.lang.Double.NaN} if the smallest X value of all data series 250 * should be used at all times. 251 */ 252 public void setMinX(double v) { 253 if (Double.isNaN(v)) 254 values.setProperty("MinX", "Auto"); 255 else 256 values.setProperty("MinX", Double.toString(v)); 257 notifyObservers("MinX"); 258 } 259 260 /** 261 * Gets the maximum X value for the plot viewport. 262 * 263 * @return The maximum value along the X axis for the graph view 264 * or {@code java.lang.Double.NaN} if the currently largest X value of all data series 265 * should be used instead. 266 */ 267 public double getMaxX() { 268 if ("Auto".equalsIgnoreCase(values.getProperty("MaxX"))) 269 return Double.NaN; 270 else 271 return Double.parseDouble(values.getProperty("MaxX")); 272 } 273 274 /** 275 * Sets the maximum X value for the plot viewport. 276 * 277 * @param v The maximum value along the X axis for the graph view 278 * or {@code java.lang.Double.NaN} if the largest X value of all data series 279 * should be used at all times. 280 */ 281 public void setMaxX(double v) { 282 if (Double.isNaN(v)) 283 values.setProperty("MaxX", "Auto"); 284 else 285 values.setProperty("MaxX", Double.toString(v)); 286 notifyObservers("MaxX"); 287 } 288 289 /** 290 * Sets the vertical grid type. 291 * 292 * @return The vertical grid type. 293 */ 294 public VGridType getVGridType() { 295 if ("VGrid_DSNumAligned".equalsIgnoreCase(values.getProperty("VGridType"))) 296 return VGridType.VGrid_DSNumAligned; 297 if ("VGrid_XAUnitAligned".equalsIgnoreCase(values.getProperty("VGridType"))) 298 return VGridType.VGrid_XAUnitAligned; 299 return VGridType.VGrid_None; 300 } 301 302 /** 303 * Gets the vertical grid type. 304 * 305 * @param v The vertical grid type. 306 */ 307 public void setVGridType(VGridType v) { 308 switch(v) { 309 case VGrid_DSNumAligned: values.setProperty("VGridType", "VGrid_DSNumAligned"); break; 310 case VGrid_XAUnitAligned: values.setProperty("VGridType", "VGrid_XAUnitAligned"); break; 311 default: values.setProperty("VGridType", "VGrid_None"); break; 312 } 313 notifyObservers("VGridType"); 314 } 315 316 /** 317 * Gets the interval between the vertical grid bars. 318 * 319 * @return The interval between the vertical grid bars. 320 */ 321 public double getVGridSize() { 322 return Double.parseDouble(values.getProperty("VGridSize")); 323 } 324 325 /** 326 * Sets the interval between the vertical grid bars. 327 * 328 * @param val The interval between the vertical grid bars. 329 */ 330 public void setVGridSize(double val) { 331 if (Double.isNaN(val) || Double.isInfinite(val) || 0 > val) 332 val = 0; 333 values.setProperty("VGridSize", Double.toString(val)); 334 notifyObservers("VGridSize"); 335 } 336 337 /** 338 * Gets the colour to use for drawing the vertical grid bars. 339 * 340 * @return The colour to use for drawing the vertical grid bars. 341 */ 342 public Color getVGridColour() { 343 String c = values.getProperty("VGridColour"); 344 int r, g, b; 345 try { r = Integer.parseInt(c.substring(0, 2), 16); } catch(NumberFormatException e) { r = 0; } 346 try { g = Integer.parseInt(c.substring(2, 4), 16); } catch(NumberFormatException e) { g = 0; } 347 try { b = Integer.parseInt(c.substring(4, 6), 16); } catch(NumberFormatException e) { b = 0; } 348 return new Color(r, g, b); 349 } 350 351 /** 352 * Sets the colour to use for drawing the vertical grid bars. 353 * @param c The colour to use for drawing the vertical grid bars. 354 */ 355 public void setVGridColour(Color c) { 356 if (null == c) 357 values.setProperty("VGridColour", "000000"); 358 else 359 values.setProperty("VGridColour", String.format("%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue())); 360 notifyObservers("VGridColour"); 361 } 362 363 /** 364 * Gets the horizontal grid type. 365 * @return The horizontal grid type. 366 */ 367 public HGridType getHGridType() { 368 if ("HGrid_Simple".equalsIgnoreCase(values.getProperty("HGridType"))) 369 return HGridType.HGrid_Simple; 370 return HGridType.HGrid_None; 371 } 372 373 /** 374 * Sets the horizontal grid type. 375 * @param v The horizontal grid type. 376 */ 377 public void setHGridType(HGridType v) { 378 switch(v) { 379 case HGrid_Simple: values.setProperty("HGridType", "HGrid_Simple"); break; 380 default: values.setProperty("HGridType", "HGrid_None"); break; 381 } 382 notifyObservers("HGridType"); 383 } 384 385 /** 386 * Gets the interval between the horizontal grib bars. 387 * 388 * @return The interval between the horizontal grib bars. 389 */ 390 public double getHGridSize() { 391 return Double.parseDouble(values.getProperty("HGridSize")); 392 } 393 394 /** 395 * Sets the interval between the horizontal grib bars. 396 * @param val The interval between the horizontal grib bars. 397 */ 398 public void setHGridSize(double val) { 399 if (Double.isNaN(val) || Double.isInfinite(val) || 0 > val) 400 val = 0; 401 values.setProperty("HGridSize", Double.toString(val)); 402 notifyObservers("HGridSize"); 403 } 404 405 406 /** 407 * Gets the colour for drawing the horizontal grid bars. 408 * 409 * @return The colour for drawing the horizontal grid bars. 410 */ 411 public Color getHGridColour() { 412 String c = values.getProperty("HGridColour"); 413 int r, g, b; 414 try { r = Integer.parseInt(c.substring(0, 2), 16); } catch(NumberFormatException e) { r = 0; } 415 try { g = Integer.parseInt(c.substring(2, 4), 16); } catch(NumberFormatException e) { g = 0; } 416 try { b = Integer.parseInt(c.substring(4, 6), 16); } catch(NumberFormatException e) { b = 0; } 417 return new Color(r, g, b); 418 } 419 420 /** 421 * Sets the colour for drawing the horizontal grid bars. 422 * 423 * @param c The colour for drawing the horizontal grid bars. 424 */ 425 public void setHGridColour(Color c) { 426 if (null == c) 427 values.setProperty("HGridColour", "000000"); 428 else 429 values.setProperty("HGridColour", String.format("%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue())); 430 notifyObservers("HGridColour"); 431 } 432 433 /** 434 * Gets the type for the x-axis. 435 * 436 * @return The type for the x-axis. 437 */ 438 public XAxisType getXAxisType() { 439 if ("XAxis_DataValSimple".equalsIgnoreCase(values.getProperty("XAxisType"))) 440 return XAxisType.XAxis_DataValSimple; 441 if ("XAxis_DataValTrans0to1".equalsIgnoreCase(values.getProperty("XAxisType"))) 442 return XAxisType.XAxis_DataValTrans0to1; 443 if ("XAxis_DataValScaledSet".equalsIgnoreCase(values.getProperty("XAxisType"))) 444 return XAxisType.XAxis_DataValScaledSet; 445 return XAxisType.XAxis_DSNum; 446 447 } 448 449 /** 450 * Sets the type for the x-axis. 451 * @param v The type for the x-axis. 452 */ 453 public void setXAxisType(XAxisType v) { 454 switch(v) { 455 case XAxis_DataValSimple: values.setProperty("XAxisType", "XAxis_DataValSimple"); break; 456 case XAxis_DataValTrans0to1: values.setProperty("XAxisType", "XAxis_DataValTrans0to1"); break; 457 case XAxis_DataValScaledSet: values.setProperty("XAxisType", "XAxis_DataValScaledSet"); break; 458 default: values.setProperty("XAxisType", "XAxis_DSNum"); break; 459 } 460 notifyObservers("XAxisType"); 461 } 462 463 /** 464 * Gets the index of the data series to use as the x-axis. 465 * 466 * @return The index of the data series to use as the x-axis. 467 */ 468 public int getXAxisSeriesIndex() { 469 return Integer.parseInt(values.getProperty("XAxisSeriesIndex")); 470 } 471 472 /** 473 * Sets the index of the data series to use as the x-axis. 474 * 475 * @param val The index of the data series to use as the x-axis. 476 */ 477 public void setXAxisSeriesIndex(int val) { 478 if (0 > val) 479 val = 0; 480 values.setProperty("XAxisSeriesIndex", Integer.toString(val)); 481 notifyObservers("XAxisSeriesIndex"); 482 } 483 484 /** 485 * Gets the scale parameter to use with the type {@code XAxis_DataValScaledSet} for 486 * scaling of X values. 487 * 488 * @return The scale parameter to use with the type {@code XAxis_DataValScaledSet} for 489 * scaling of X values. 490 */ 491 public double getXAxisScaleValue() { 492 double val = Double.parseDouble(values.getProperty("XAxisScaleValue")); 493 if (Double.isNaN(val) || Double.isInfinite(val)) 494 return 1.; 495 return val; 496 } 497 498 /** 499 * Sets the scale parameter to use with the type {@code XAxis_DataValScaledSet} for 500 * scaling of X values. 501 * 502 * @param val scale parameter to use with the type {@code XAxis_DataValScaledSet} for 503 * scaling of X values. 504 */ 505 public void setXAxisScaleValue(double val) { 506 if (Double.isNaN(val) || Double.isInfinite(val)) 507 val = 1.; 508 values.setProperty("XAxisScaleValue", Double.toString(val)); 509 notifyObservers("XAxisScaleValue"); 510 } 511 512 /** 513 * Gets whether the data points in the vicinity of the mouse cursor should be highlighted. 514 * (Note, this is a hidden setting and cannot be changes via the GUI.) 515 * 516 * @return {@code true} if the data points in the vicinity of the mouse cursor should be highlighted, 517 * {@code false} otherwise. 518 */ 519 public boolean getHighlightDataPoints() { return "1".equals(values.getProperty("HighlightDataPoints")); } 520 521 /** 522 * Gets whether the data points in the vicinity of the mouse cursor should be highlighted. 523 * (Note, this is a hidden setting and cannot be changes via the GUI.) 524 * 525 * @param v {@code true} if the data points in the vicinity of the mouse cursor are to be highlighted, 526 * {@code false} otherwise. 527 */ 528 public void setHighlightDataPoints(boolean v) { 529 values.setProperty("HighlightDataPoints", v ? "1" : "0"); 530 checkDisableHighlightingForOldJava(); 531 notifyObservers("HighlightDataPoints"); 532 } 533 534 /** 535 * If the Java version is too old, data point highlighting is disabled. 536 */ 537 private void checkDisableHighlightingForOldJava() { 538 if (!LiveGraph.application().runsCorrectJavaVersion()) 539 values.setProperty("HighlightDataPoints", "0"); 540 } 541 542 } // public class GraphSettings