diff --git a/.classpath b/.classpath deleted file mode 100644 index 67de708..0000000 --- a/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.gitignore b/.gitignore index 02b6b93..525bfcc 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,97 @@ target/ tmp/ img/ +### Gradle template +.gradle +/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/sonarlint/** + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ +cmake-build-release/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + diff --git a/.project b/.project deleted file mode 100644 index 13f3a24..0000000 --- a/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - OpenLogViewer - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.maven.ide.eclipse.maven2Builder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - org.maven.ide.eclipse.maven2Nature - org.eclipse.jdt.core.javanature - - diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6a0d67e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: java +jdk: +- oraclejdk8 +- oraclejdk9 +- openjdk8 + +cache: + directories: + - "${HOME}/.gradle" + +addons: + sonarcloud: + organization: "expeditioneer-github" + token: + secure: rOEze8AzsNOJ7eFZYOqSji3dXLiVvyTr4NsLCxNNWLtPf3wsnr25L/pzyTZtE01NWOg4njdV55FUJc9TrbMaxG7O2gntP4IAVjS7Co05jM9GF4YWtL5y5ZxxjCjae32aqagjMwyzR3YskSZ0QgG0HW+Sbvlnxc2adK3ORc9i8hOgjj4Z3jneAR1w2yCgqB3MMPvnJtDgLqJG6hixDTLi2SiKnp3dDrJ3nTuKXhasOqSOWskoetMh1W3PkQh4/A/B1e7lq+Dy9sW4KlvVaGnGpyY5u3yR6EEaC0mRXUi6BYJfvxpF1YB1Gl7K7Yy2u+9akPTOSPgyUXMRXfpMO9X0+JxrJ7e8Hs1C1CSIuSt5zo733B+2Ar6DtG1gH0a7gUwANUk1+S3GXOWMQ7ApwEtSgIu7P8JoBOnJ9CMhufQmchpiAvmF7iAqYV2YVhX0lnS8P7J4+qm2kIdfAsOaKWPrALroKP0paGpQaq4Z4nQtGWZ/2wuyIqhgRDk1FDRv9+S64/mEIolYme9XzchilhgDWvaQT1GVnw1pPZqIvSLsI43jihmgQVxfa5VcCRyAKxOMKmHyoqvWsDzg8h6DBOagHjxhvNXLI70p9vxkhdMM/qOqSx3k6L1gnZ8sAce5TyUpeqfh1vFj7H0SovFm5UPxztuC1JWd6V19JUXeqCQV55c= + +script: + - "./gradlew dependencyUpdates clean test shadow sonarqube" diff --git a/Documentation/gpl.v3.full.txt b/LICENSE similarity index 100% rename from Documentation/gpl.v3.full.txt rename to LICENSE diff --git a/README.md b/README.md index 57acc27..4b37bb3 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,113 @@ -# OpenLogViewer - -OpenLogViewer, or OLV for short, is an open source project originally concieved -by Bryan Harris. He says that he created it due to boredom, but that he intends -for it to be reasonably easy to use. Ben Fenner, and to a lesser extent, Fred -Cooke have done significant work to turn that dream into reality with UI and -performance enhancements across the board. - -Gufi, as Bryan is known to his friends, would love for the program to become -mainstream in the Automotive Datalog area as a tool. We feel that it's well on -its way to doing just that. - -### Where do I get it? - -Download the latest release from the official [OLV website](http://olv.diyefi.org) -or get the latest development version from the [build server!](http://builds.freeems.org) -. Until 0.0.3 is released, the development version is a far better choice. - -### Prerequisites - -#### Running a precompiled version - -For using the precompiled application you only need a Java Runtime Environment -(JRE) version 6 or above. - -#### Building the latest from source - -If you want to build the latest from source to make customisations, then you will -need a Java Development Kit (JDK) version 6 or above AND maven 3. Maven 2 is -not suitable as the project is configured for a number of plugins which are not -compatible with maven 2. Additionally maven 2 does not provide the 100% stable -build environment, which maven 3 does. Get maven from this link and follow the -install instructions further down the page. - -http://maven.apache.org/download.html - -Additionally, you need to install the included settings.xml file in your ~/.m2 -directory. This allows your build to include artifacts that are only available -from the DIYEFI.org Maven repository. - -You can get the source from one of the following repositories; use the network -function to figure out whose is newest (though not necessarily best!): - -https://github.com/FreeEMS/OpenLogViewer - Tested commits -https://github.com/fredcooke/OpenLogViewer - Latest from Fred -https://github.com/BenFenner/OpenLogViewer - Latest from Ben - -A direct link to the network function: - -https://github.com/FreeEMS/OpenLogViewer/network - -Use git to obtain the source in an efficient way, for example: - -git clone git://github.com/FreeEMS/OpenLogViewer.git - -#### Using Ant - -Ant is deprecated in the professional development world, for good reasons, and -as such is not supported as a build tool for this project. - -### Running OLV - -To run an OLV jar in a graphical desktop environment such as Microsoft Windows -Gnome, KDE, or Mac OS X, simply double click the jar file. To run it from the -command line use the following command: - -java -jar OLV.jar - -Where "OLV.jar" is replaced with the name of the file that you downloaded. - -If you're using Maven to build from source and run OLV, then the following -simple command is all you need: - -mvn -DskipTests - -This does the same as "mvn install" and "mvn exec:exec" back to back. You may -wish to clean the build directory before building and running, as you'd expect -the required command is simply this: - -mvn clean - -Up to date documentation can be generated using maven in the following way: - -mvn site:site - -You can find the html index file in the target/site/ directory once complete. - -### OLV Website - -If you don't want to build the latest from source then you can pick up the last -release from the extremely basic OLV website below. Automatically generated -documentation is available from the same site. - -http://olv.diyefi.org - -### OLV Status - -Currently the application has an excellent mouse-based navigation UI. Adding -and associating fields with traces is still sub-par, but should be fixed soon. - -The OLV development team are commited to regular releases of working software. -This is the agile way, and as such have a clear roadmap for future releases. - -http://issues.freeems.org/roadmap_page.php?project_id=15 - -Thanks for using this tool! We hope you love it as much as we do. - -The OLV Team. - +# OpenLogViewer + +[![Build Status](https://travis-ci.org/expeditioneer/OpenLogViewer.svg?branch=master)](https://travis-ci.org/expeditioneer/OpenLogViewer) +[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=org.diyefi.openlogviewer&metric=alert_status)](https://sonarcloud.io/dashboard?id=org.diyefi.openlogviewer) +[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=org.diyefi.openlogviewer&metric=ncloc)](https://sonarcloud.io/dashboard?id=org.diyefi.openlogviewer) +[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=org.diyefi.openlogviewer&metric=bugs)](https://sonarcloud.io/dashboard?id=org.diyefi.openlogviewer) + +OpenLogViewer, or OLV for short, is an open source project originally concieved +by Bryan Harris. He says that he created it due to boredom, but that he intends +for it to be reasonably easy to use. Ben Fenner, and to a lesser extent, Fred +Cooke have done significant work to turn that dream into reality with UI and +performance enhancements across the board. + +Gufi, as Bryan is known to his friends, would love for the program to become +mainstream in the Automotive Datalog area as a tool. We feel that it's well on +its way to doing just that. + +### Where do I get it? + +Download the latest release from the official [OLV website](http://olv.diyefi.org) +or get the latest development version from the [build server!](http://builds.freeems.org) +. Until 0.0.3 is released, the development version is a far better choice. + +### Prerequisites + +#### Running a precompiled version + +For using the precompiled application you only need a Java Runtime Environment (JRE) version 8 or above. + +#### Building the latest from source + +If you want to build the latest from source to make customisations, then you will +need a Java Development Kit (JDK) version 6 or above AND maven 3. Maven 2 is +not suitable as the project is configured for a number of plugins which are not +compatible with maven 2. Additionally maven 2 does not provide the 100% stable +build environment, which maven 3 does. Get maven from this link and follow the +install instructions further down the page. + +http://maven.apache.org/download.html + +Additionally, you need to install the included settings.xml file in your ~/.m2 +directory. This allows your build to include artifacts that are only available +from the DIYEFI.org Maven repository. + +You can get the source from one of the following repositories; use the network +function to figure out whose is newest (though not necessarily best!): + +https://github.com/FreeEMS/OpenLogViewer - Tested commits +https://github.com/fredcooke/OpenLogViewer - Latest from Fred +https://github.com/BenFenner/OpenLogViewer - Latest from Ben + +A direct link to the network function: + +https://github.com/FreeEMS/OpenLogViewer/network + +Use git to obtain the source in an efficient way, for example: + +git clone git://github.com/FreeEMS/OpenLogViewer.git + +#### Using Ant + +Ant is deprecated in the professional development world, for good reasons, and +as such is not supported as a build tool for this project. + +### Running OLV + +To run an OLV jar in a graphical desktop environment such as Microsoft Windows +Gnome, KDE, or Mac OS X, simply double click the jar file. To run it from the +command line use the following command: + +java -jar OLV.jar + +Where "OLV.jar" is replaced with the name of the file that you downloaded. + +If you're using Maven to build from source and run OLV, then the following +simple command is all you need: + +mvn -DskipTests + +This does the same as "mvn install" and "mvn exec:exec" back to back. You may +wish to clean the build directory before building and running, as you'd expect +the required command is simply this: + +mvn clean + +Up to date documentation can be generated using maven in the following way: + +mvn site:site + +You can find the html index file in the target/site/ directory once complete. + +### OLV Website + +If you don't want to build the latest from source then you can pick up the last +release from the extremely basic OLV website below. Automatically generated +documentation is available from the same site. + +http://olv.diyefi.org + +### OLV Status + +Currently the application has an excellent mouse-based navigation UI. Adding +and associating fields with traces is still sub-par, but should be fixed soon. + +The OLV development team are commited to regular releases of working software. +This is the agile way, and as such have a clear roadmap for future releases. + +http://issues.freeems.org/roadmap_page.php?project_id=15 + +Thanks for using this tool! We hope you love it as much as we do. + +The OLV Team. + diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 1d0fdc8..0000000 --- a/RELEASE.md +++ /dev/null @@ -1,52 +0,0 @@ -# Releases - -Releases are performed by one person with appropriate credentials to deploy the -artifacts and upload the documentation. For a release to occur in Maven a number -of things must be true. - - - The application builds without any errors - - Repository clean - no uncommitted changes - - Repository shared - no local changes unpushed - - All unit tests pass - -Additionally the following conditions must be checked by the release manager. -All of these are to be done after the last commit to be included in the release. -If new commits go in to remedy issues that are found, all checks should be done -again on the latest code base. - - - All issues with target == next version are not only resolved, but also closed - - No known regressions from last release present in current build - - No known regressions in features added since the last release - - No inappropriate string literals shall be present in the code base - - All localisation files complete and contain no English, except the English one - - No commented out code shall be present in the code base - - No SNAPSHOT versions shall be depended upon, including plugins - - mvn site:site style counts are equal to, or better than the last release - - findbugs shows no serious issues and equal to, or less than the last release - - Test data-log files load correctly and display correctly for all decoders - - mvn install on mac produces working bin.jar, linux.tar.bz2, .deb, .exe, .dmg - - Windows exe executes and displays properly on XP and 7 - - Linux zip and deb function correctly and display properly on a variety of wms - - Mac dmg and app.zip function correctly and display properly on 10.6 and 10.7 - -Note, issues listed for future releases beyond the release in question can, and -likely are present in the code that is about to be released. This is normal and -completely OK. - -# Platform Check List - - - Full-screen entry/exit for each platform - - Button behaviour for each platform - - Key bindings for each platform - - Settings file/dir behaviour on each platform - - Panel sizes make sense and don't affect functionality - -# Post Release - - - Update all repos - - Update the website - - Update the issue tracker - - Announce on forum and facebook - - Tag SNAPSHOT version for git describe - - git push --tags to all repos - diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..1d5ab4c --- /dev/null +++ b/build.gradle @@ -0,0 +1,75 @@ +plugins { + id 'com.github.johnrengelman.shadow' version '2.0.4' + id 'com.gorylenko.gradle-git-properties' version '1.5.1' + id 'org.sonarqube' version '2.6.2' + id 'com.github.ben-manes.versions' version '0.20.0' +} + +apply plugin: 'java' +apply plugin: 'jacoco' +apply plugin: 'maven' +apply plugin: 'com.github.johnrengelman.shadow' + + +group = 'org.diyefi.openlogviewer' +version = '0.0.3-SNAPSHOT' + +description = 'OpenLogViewer is a free, open source, cross-platform data-log visualisation application that currently supports many CSV data-log formats (including MegaSquirt style), and FreeEMS binary data-logs. OpenLogViewer is currently in its infancy. While in the future it will be amazing, right now it has all of the basics that you need.' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +configurations.all { +} + +processResources { + filesMatching('**/buildInfo.properties') { + expand(project.properties) + } +} + +jar { + manifest { + attributes 'Main-Class': 'org.diyefi.openlogviewer.OpenLogViewer' + } +} + +shadowJar { + dependencies { + exclude(dependency('com.yuvimasory:orange-extensions:1.3.0')) + } +} + +repositories { + maven { url "http://repo.maven.apache.org/maven2" } +} + +dependencies { + implementation 'org.apache.logging.log4j:log4j-api:2.11.0' + implementation 'org.apache.logging.log4j:log4j-core:2.11.0' + implementation 'org.apache.commons:commons-lang3:3.7' + implementation 'com.yuvimasory:orange-extensions:1.3.0' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.2.0' + testImplementation 'org.junit.platform:junit-platform-surefire-provider:1.2.0' + testImplementation 'org.mockito:mockito-core:2.19.0' + testImplementation 'org.mockito:mockito-junit-jupiter:2.19.0' + testImplementation 'org.assertj:assertj-core:3.10.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.1' +} + +test { + useJUnitPlatform() +} + +sonarqube { + properties { + property "sonar.projectName", "OpenLogViewer" + property "sonar.projectKey", "org.diyefi.openlogviewer" + } +} + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..01b8bf6 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3ec500c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Jun 27 09:58:39 CEST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 334c4d2..0000000 --- a/pom.xml +++ /dev/null @@ -1,398 +0,0 @@ - - 4.0.0 - - org.diyefi.openlogviewer - OpenLogViewer - jar - 0.0.3-SNAPSHOT - - OpenLogViewer - http://olv.diyefi.org - - - DIYEFI.org - http://www.diyefi.org - - - - OpenLogViewer is a free, open source, cross-platform data-log visualisation application that currently supports many CSV data-log formats (including MegaSquirt style), and FreeEMS binary data-logs. OpenLogViewer is currently in its infancy. While in the future it will be amazing, right now it has all of the basics that you need. - - - MantisBT - http://issues.freeems.org - - - - scm:git:git://github.com/FreeEMS/OpenLogViewer.git - https://github.com/FreeEMS/OpenLogViewer - scm:git:git@github.com:FreeEMS/OpenLogViewer.git - - - - http://mvn.diyefi.org/nexus/content/repositories/releases/org/diyefi/openlogviewer/OpenLogViewer/ - - freeemsreleases - http://mvn.diyefi.org/nexus/content/repositories/releases - - - freeemssnapshots - http://mvn.diyefi.org/nexus/content/repositories/snapshots - - - olvsite - OLV Website - scp://raptor:443/home/olv/site/releases/${project.version}/ - - - - - - GPL V3 - manual - You're free to download and use OpenLogViewer for any purpose, including - viewing MegaSquirt logs as a free alternative to MegaLogViewer (MLV) - - - - - - Gufi - Bryan Harris - - Founder - Hacker - - - - Fred - Fred Cooke - - FreeEMS Plugin - Quality Control - - - - BenFenner - Ben Fenner - - User Interface - Refactoring - - - - - - - Preston Saunders - - - - - 1.8 - -Xms128m - -Xmx1024m - UTF-8 - http://forum.diyefi.org/viewforum.php?f=32 - http://issues.freeems.org - - - - - - org.apache.maven.plugins - maven-jxr-plugin - 2.5 - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 2.9 - - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.17 - - src/site/fredsChecks.xml - - - - - checkstyle - - - - - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.2 - - Max - Low - - - - org.codehaus.mojo - jdepend-maven-plugin - 2.0 - - - org.apache.maven.plugins - maven-pmd-plugin - 3.6 - - 20 - 1.6 - - - - /rulesets/java/basic.xml - /rulesets/java/braces.xml - /rulesets/java/clone.xml - /rulesets/java/codesize.xml - - ${project.basedir}/src/site/pmd/rulesets/controversial.xml - ${project.basedir}/src/site/pmd/rulesets/coupling.xml - ${project.basedir}/src/site/pmd/rulesets/design.xml - - /rulesets/java/finalizers.xml - /rulesets/java/imports.xml - - /rulesets/java/junit.xml - - /rulesets/java/optimizations.xml - /rulesets/java/sunsecure.xml - /rulesets/java/strictexception.xml - /rulesets/java/strings.xml - /rulesets/java/typeresolution.xml - - /rulesets/java/unusedcode.xml - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.4 - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - org.codehaus.mojo - javancss-maven-plugin - 2.1 - - - org.apache.maven.plugins - maven-surefire-report-plugin - 2.19.1 - - - - - - install exec:exec - - - false - src/main/resources - - **/* - - - - true - src/main/resources/build/ - build - - buildInfo.xml - - - - - - pl.project13.maven - git-commit-id-plugin - 2.2.1 - - - - revision - - - - - - false - true - 7 - -DEV - false - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 1.4.1 - - - validate - enforce-versions - - enforce - - - - - [3.3.9,) - - - [1.8,) - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - - ${java.version} - ${java.version} - - - - org.codehaus.mojo - exec-maven-plugin - 1.5.0 - - - - java - - ${project.initial.heap} - ${project.maximum.heap} - - -jar - ${project.basedir}/target/${project.artifactId}-${project.version}-bin.jar - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.12 - - - maven-version - - maven-version - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.6 - - - bin - package - - single - - - - src/main/assembly/runnable.xml - - - - ${project.groupId}.${project.artifactId} - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.0.2 - - - - ${project.groupId}.${project.artifactId} - - - - - - org.apache.maven.plugins - maven-site-plugin - 3.5.1 - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 - - @{project.version} - - - - - - org.apache.maven.wagon - wagon-ssh - 2.10 - - - - - - - - - - - junit - junit - 4.12 - test - - - - - org.apache.commons - commons-lang3 - 3.1 - - - - - - - com.apple.eawt - ui - 1.6.0_24 - - - - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..1c994d4 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'OpenLogViewer' diff --git a/settings.xml b/settings.xml deleted file mode 100644 index 2b17d09..0000000 --- a/settings.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - diyefi.org - - - - - - diyefi.org - - - maven.diyefi.org - DIYEFI.org Maven Repo - - true - always - fail - - - false - never - fail - - http://maven.diyefi.org/content/groups/DIYEFI.org/ - default - - - - - - - central - - true - - - - central - - false - - Central CNAME Redirect - http://repo1.maven.org/maven2 - - - - - diff --git a/src/main/assembly/runnable.xml b/src/main/assembly/runnable.xml deleted file mode 100644 index 6f589ec..0000000 --- a/src/main/assembly/runnable.xml +++ /dev/null @@ -1,26 +0,0 @@ - - bin - - jar - - false - - - / - true - true - runtime - - - META-INF/MANIFEST.MF - - - - com.apple.eawt:ui - - - - \ No newline at end of file diff --git a/src/main/java/org/diyefi/openlogviewer/FileExtensions.java b/src/main/java/org/diyefi/openlogviewer/FileExtensions.java index 042a241..da29a08 100644 --- a/src/main/java/org/diyefi/openlogviewer/FileExtensions.java +++ b/src/main/java/org/diyefi/openlogviewer/FileExtensions.java @@ -1,18 +1,38 @@ package org.diyefi.openlogviewer; -public final class FileExtensions { - public static final String STAR_DOT = "*."; - - public static final String LA = "la"; - public static final String BIN = "bin"; - public static final String CSV = "csv"; - public static final String LOG = "log"; - public static final String XLS = "xls"; - public static final String MSL = "msl"; - - /** - * Prevent instantiation. - */ - private FileExtensions() { - } +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public enum FileExtensions { + STAR_DOT("*."), + LA("la"), + BIN("bin"), + CSV("csv"), + LOG("log"), + XLS("xls"), + MSL("msl"); + + private static final Map lookupByExtension = new HashMap<>(); + + static { + Arrays.stream(FileExtensions.values()) + .forEach(fileExtension -> lookupByExtension.put(fileExtension.getExtension(), fileExtension)); + } + + private final String extension; + + public static FileExtensions getByExtension(String extension) { + return Optional.ofNullable(lookupByExtension.get(extension)) + .orElseThrow(() -> new IllegalArgumentException("Unsupported file extension '" + extension + "'")); + } + + FileExtensions(String extension) { + this.extension = extension; + } + + public String getExtension() { + return extension; + } } diff --git a/src/main/java/org/diyefi/openlogviewer/OpenLogViewer.java b/src/main/java/org/diyefi/openlogviewer/OpenLogViewer.java index ae0887f..5082cbb 100644 --- a/src/main/java/org/diyefi/openlogviewer/OpenLogViewer.java +++ b/src/main/java/org/diyefi/openlogviewer/OpenLogViewer.java @@ -28,52 +28,12 @@ */ package org.diyefi.openlogviewer; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.IllegalComponentStateException; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.IOException; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.util.List; -import java.util.ArrayList; -import java.util.Locale; -import java.util.Properties; -import java.util.ResourceBundle; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.filechooser.FileFilter; - +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.diyefi.openlogviewer.decoder.AbstractDecoder; import org.diyefi.openlogviewer.decoder.CSVTypeLog; import org.diyefi.openlogviewer.decoder.FreeEMSBin; -import org.diyefi.openlogviewer.filefilters.CSVFileFilter; -import org.diyefi.openlogviewer.filefilters.FreeEMSBinFileFilter; -import org.diyefi.openlogviewer.filefilters.FreeEMSLAFileFilter; -import org.diyefi.openlogviewer.filefilters.LogFileFilter; -import org.diyefi.openlogviewer.filefilters.MSTypeFileFilter; -import org.diyefi.openlogviewer.filefilters.FreeEMSFileFilter; +import org.diyefi.openlogviewer.filefilters.*; import org.diyefi.openlogviewer.genericlog.GenericLog; import org.diyefi.openlogviewer.graphing.EntireGraphingPanel; import org.diyefi.openlogviewer.graphing.MultiGraphLayeredPane; @@ -84,651 +44,625 @@ import org.diyefi.openlogviewer.subframes.MacOSAboutHandler; import org.diyefi.openlogviewer.utils.Utilities; +import javax.swing.*; +import javax.swing.filechooser.FileFilter; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.*; +import java.util.List; + public final class OpenLogViewer extends JFrame { - public static final String NEWLINE = System.getProperty(Keys.LINE_SEPARATOR); - - private static final long serialVersionUID = 1L; - - private static final Properties buildInfo = new Properties(); - - private static final String APPLICATION_NAME = OpenLogViewer.class.getSimpleName(); - private static final String SETTINGS_DIRECTORY = "." + APPLICATION_NAME; - - private static final String GIT_DESCRIBE_KEY = "git.commit.id.describe"; - - // TODO localise and refactor these: - private static final String PROPERTIES_FILENAME = "OLVAllProperties.olv"; - - private static final String NAME_OF_LAST_FILE_KEY = "lastFingFile"; - private static final String NAME_OF_LAST_DIR_KEY = "lastFingDir"; - private static final String NAME_OF_LAST_CHOOSER_CLASS = "chooserClass"; - - // Real vars start here, many will probably get ripped out later - private static final int GRAPH_PANEL_WIDTH = 600; - private static final int GRAPH_PANEL_HEIGHT = 420; - - private static final String OS_NAME = System.getProperty(Keys.OS_NAME); - private static final boolean IS_MAC_OS_X = OS_NAME.contains("OS X"); // TN2110 - private static final boolean IS_WINDOWS = OS_NAME.contains("Windows"); - private static final boolean IS_LINUX = OS_NAME.contains("Linux"); - - private static OpenLogViewer mainAppRef; - private static ResourceBundle labels; - - private final String applicationTitle; - private final String applicationVersion; - private final EntireGraphingPanel graphingPanel; - private final FooterPanel footerPanel; - private final OptionFrameV2 optionFrame; - private final PropertiesPane prefFrame; - - private final List properties; - private AbstractDecoder decoderInUse; - private final JMenuBar menuBar; - private boolean fullscreen; - - private int extendedState; - private Point location; - private Dimension size; - private int containingDevice; - - public OpenLogViewer() { - try { - buildInfo.loadFromXML(getClass().getClassLoader().getResourceAsStream("build/buildInfo.xml")); - } catch (IOException e) { - System.out.println("Uh oh, looks like a hacked copy! UNSUPPORTED VERSION! DO NOT USE!"); - } finally { - String preliminaryVersion = buildInfo.getProperty(GIT_DESCRIBE_KEY); - if (preliminaryVersion == null || "".equals(preliminaryVersion.trim())) { - System.out.println("Application version not found! UNSUPPORTED VERSION! DO NOT USE!"); - applicationVersion = "UNSUPPORTED VERSION! DO NOT USE!"; - buildInfo.setProperty(GIT_DESCRIBE_KEY, applicationVersion); - } else { - applicationVersion = buildInfo.getProperty(GIT_DESCRIBE_KEY); - buildInfo.setProperty(GIT_DESCRIBE_KEY, applicationVersion); - } - } - - applicationTitle = APPLICATION_NAME + " " + applicationVersion; - buildInfo.setProperty("application.title", applicationTitle); - - prefFrame = new PropertiesPane(labels, SETTINGS_DIRECTORY); - properties = new ArrayList(); - prefFrame.setProperties(properties); - - footerPanel = new FooterPanel(labels); - optionFrame = new OptionFrameV2(labels); - graphingPanel = new EntireGraphingPanel(labels); - graphingPanel.setPreferredSize(new Dimension(GRAPH_PANEL_WIDTH, GRAPH_PANEL_HEIGHT)); - - setDefaultCloseOperation(EXIT_ON_CLOSE); - setTitle(applicationTitle); - setLayout(new BorderLayout()); - setFocusable(true); - - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(graphingPanel, BorderLayout.CENTER); - mainPanel.add(footerPanel, BorderLayout.SOUTH); - add(mainPanel, BorderLayout.CENTER); - - final JMenuItem openFileMenuItem = new JMenuItem(labels.getString(Text.FILE_MENU_ITEM_OPEN_NAME)); - openFileMenuItem.setName(Text.FILE_MENU_ITEM_OPEN_NAME); - openFileMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - openChosenFile(); - } - }); - - final JMenuItem reloadFileMenuItem = new JMenuItem(labels.getString(Text.FILE_MENU_ITEM_RELOAD_NAME)); - reloadFileMenuItem.setName(Text.FILE_MENU_ITEM_RELOAD_NAME); - reloadFileMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - openLastFile(); - } - }); - - final JMenuItem quitFileMenuItem = new JMenuItem(labels.getString(Text.FILE_MENU_ITEM_QUIT_NAME)); - quitFileMenuItem.setName(Text.FILE_MENU_ITEM_QUIT_NAME); - quitFileMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - OpenLogViewer.getInstance().quit(); - } - }); - - final JMenuItem fullScreenViewMenuItem = new JMenuItem(labels.getString(Text.VIEW_MENU_ITEM_FULL_SCREEN_NAME)); - fullScreenViewMenuItem.setName(Text.VIEW_MENU_ITEM_FULL_SCREEN_NAME); - fullScreenViewMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - enterFullScreen(); - } - }); - - final JMenuItem scaleAndColorViewMenuItem = new JMenuItem(labels.getString(Text.VIEW_MENU_ITEM_SCALE_AND_COLOR_NAME)); - scaleAndColorViewMenuItem.setName(Text.VIEW_MENU_ITEM_SCALE_AND_COLOR_NAME); - scaleAndColorViewMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - prefFrame.setVisible(true); - } - }); - - final JMenuItem fieldsAndDivisionsViewMenuItem = new JMenuItem(labels.getString(Text.VIEW_MENU_ITEM_FIELDS_AND_DIVISIONS_NAME)); - fieldsAndDivisionsViewMenuItem.setName(Text.VIEW_MENU_ITEM_FIELDS_AND_DIVISIONS_NAME); - fieldsAndDivisionsViewMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - optionFrame.setVisible(true); - } - }); - - final JMenuItem aboutMenuItem = new JMenuItem(labels.getString(Text.HELP_MENU_ITEM_ABOUT_NAME)); - aboutMenuItem.setName(Text.HELP_MENU_ITEM_ABOUT_NAME); - aboutMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - AboutFrame.show(buildInfo); - } - }); - - /* - * 13 January 2012 Had Chick-fil-A #1 meal with no pickle and Dr Pepper for lunch. - * Dr Pepper with no period. "Dude didn't even get his degree." Either that or he is British. - * 1 November 2011 Migrated Gufi's menu from the pointless class it's in to here. - * 22 October 2011 Left Gufi's menu in place for future dev's enjoyment. - * - * 5 February 2011 meal for the night DO NOT EDIT MENU! - * Sesame chicken alacarte - * chicken lo mein alacarte - * orange chicken x2 - */ - - final JMenu fileMenu = new JMenu(labels.getString(Text.FILE_MENU_NAME)); - fileMenu.setName(Text.FILE_MENU_NAME); - fileMenu.add(openFileMenuItem); - fileMenu.add(reloadFileMenuItem); - if (!IS_MAC_OS_X) { - fileMenu.add(quitFileMenuItem); - } - - final JMenu viewMenu = new JMenu(labels.getString(Text.VIEW_MENU_NAME)); - viewMenu.setName(Text.VIEW_MENU_NAME); - viewMenu.add(fullScreenViewMenuItem); - viewMenu.add(scaleAndColorViewMenuItem); - viewMenu.add(fieldsAndDivisionsViewMenuItem); - - final JMenu helpMenu = new JMenu(labels.getString(Text.HELP_MENU_NAME)); - helpMenu.setName(Text.HELP_MENU_NAME); - helpMenu.add(aboutMenuItem); - - menuBar = new JMenuBar(); - menuBar.add(fileMenu); - menuBar.add(viewMenu); - if (IS_MAC_OS_X) { - new MacOSAboutHandler(buildInfo); - } else { - menuBar.add(helpMenu); - } - setJMenuBar(menuBar); - - //Listener stuff - addComponentListener(graphingPanel); - setupWindowKeyBindings(this); - - setName(applicationTitle); - - pack(); - - setVisible(true); - } - - /** - * The entry point of OLV! - * - * @param args the command line arguments - */ - public static void main(final String[] args) { - EventQueue.invokeLater(new Runnable() { - - @Override - public void run() { - final Locale currentLocale = Locale.getDefault(); - - labels = ResourceBundle.getBundle(OpenLogViewer.class.getPackage().getName() + ".Labels", currentLocale); - - final String lookAndFeel; - final String systemLookAndFeel = UIManager.getSystemLookAndFeelClassName(); - if (IS_MAC_OS_X) { - System.setProperty(Keys.APPLE_LAF_USE_SCREEN_MENU_BAR, Boolean.TRUE.toString()); - } - lookAndFeel = systemLookAndFeel; - - try { - UIManager.setLookAndFeel(lookAndFeel); - } catch (UnsupportedLookAndFeelException e) { - e.printStackTrace(); - System.out.println(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_ONE)); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - System.out.println(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_TWO)); - } catch (InstantiationException e) { - e.printStackTrace(); - System.out.println(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_THREE)); - } catch (IllegalAccessException e) { - e.printStackTrace(); - System.out.println(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_FOUR)); - } - - mainAppRef = new OpenLogViewer(); - - if (args.length > 0) { - final File toOpen = new File(args[0]).getAbsoluteFile(); - if (toOpen.exists() && toOpen.isFile()) { - if (args.length > 1) { - System.out.println(args.length + labels.getString(Text.TOO_MANY_ARGUMENTS) + args[0]); - } else { - System.out.println(labels.getString(Text.ATTEMPTING_TO_OPEN_FILE) + args[0]); - } - final FileFilter ms = new MSTypeFileFilter(labels); - final FileFilter fe = new FreeEMSFileFilter(labels); - if (fe.accept(toOpen) || ms.accept(toOpen)) { - mainAppRef.openFile(toOpen, mainAppRef.generateChooser()); - } else { - System.out.println(labels.getString(Text.FILE_TYPE_NOT_SUPPORTED) + args[0]); - mainAppRef.quit(); - } - } else { - System.out.println(labels.getString(Text.FILE_ARGUMENT_NOT_GOOD) + args[0]); - mainAppRef.quit(); - } - } - } - }); - } - - public void quit() { - final WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING); - Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev); - } - - public void openChosenFile() { - final JFileChooser fileChooser = generateChooser(); - final int acceptValue = fileChooser.showOpenDialog(this); - if (acceptValue == JFileChooser.APPROVE_OPTION) { - final File fileToOpen = fileChooser.getSelectedFile(); - if (!openFile(fileToOpen, fileChooser)) { - JOptionPane.showMessageDialog(mainAppRef, labels.getObject(Text.OPEN_FILE_ERROR_MESSAGE) - + NEWLINE + fileToOpen.getAbsolutePath(), - labels.getString(Text.OPEN_FILE_ERROR_TITLE), - JOptionPane.ERROR_MESSAGE); - } - } - } - - public void openLastFile() { - final String lastFingFile = getApplicationWideProperty(NAME_OF_LAST_FILE_KEY); - final String chooserClass = getApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); - if (chooserClass != null && lastFingFile != null) { - final File fileToOpen = new File(lastFingFile); - final JFileChooser fileChooser = generateChooser(); - if (!openFile(fileToOpen, fileChooser)) { - JOptionPane.showMessageDialog(mainAppRef, labels.getObject(Text.OPEN_LAST_FILE_ERROR_MESSAGE) - + NEWLINE + fileToOpen.getAbsolutePath(), - labels.getString(Text.OPEN_LAST_FILE_ERROR_TITLE), - JOptionPane.ERROR_MESSAGE); - } - } else { - JOptionPane.showMessageDialog(mainAppRef, labels.getObject(Text.OPEN_LAST_FILE_MISSING_PROPERTY_MESSAGE), - labels.getString(Text.OPEN_LAST_FILE_MISSING_PROPERTY_TITLE), - JOptionPane.ERROR_MESSAGE); - } - } - - public boolean openFile(final File fileToOpen, final JFileChooser fileChooser) { - if (fileToOpen.exists()) { - if (decoderInUse != null) { - // Clear out all references to data that we don't need and thereby ensure that we have lots of memory free for data we're about to gather! - final GenericLog logInUse = decoderInUse.getDecodedLog(); - if (logInUse != null) { - logInUse.clearOut(); // This is the wrong approach. The correct approach is to reuse the object, try that next... - } - decoderInUse = null; - setLog(null); - } // else haven't read in a log yet. - - setTitle(applicationTitle + " - " + fileToOpen.getName()); - saveApplicationWideProperty(NAME_OF_LAST_DIR_KEY, fileToOpen.getParent()); - saveApplicationWideProperty(NAME_OF_LAST_FILE_KEY, fileToOpen.getPath()); - saveApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS, fileChooser.getFileFilter().getClass().getCanonicalName()); - - if (FileExtensions.BIN.equals(Utilities.getExtension(fileToOpen)) - || FileExtensions.LA.equals(Utilities.getExtension(fileToOpen)) - || (fileChooser.getFileFilter() instanceof FreeEMSFileFilter)) { - decoderInUse = new FreeEMSBin(fileToOpen, labels); - } else { - decoderInUse = new CSVTypeLog(fileToOpen, labels); - } - return true; - } else { - setTitle(applicationTitle); - return false; - } - } - - public JFileChooser generateChooser() { - final JFileChooser fileChooser = new JFileChooser(); - final String lastFingFile = getApplicationWideProperty(NAME_OF_LAST_FILE_KEY); - - if (lastFingFile != null) { - fileChooser.setSelectedFile(new File(lastFingFile)); - } else { - final String lastFingDir = getApplicationWideProperty(NAME_OF_LAST_DIR_KEY); - if (lastFingDir != null) { - fileChooser.setCurrentDirectory(new File(lastFingDir)); - } - } - - fileChooser.addChoosableFileFilter(new FreeEMSFileFilter(labels)); - fileChooser.addChoosableFileFilter(new FreeEMSBinFileFilter()); - fileChooser.addChoosableFileFilter(new FreeEMSLAFileFilter()); - fileChooser.addChoosableFileFilter(new CSVFileFilter()); - fileChooser.addChoosableFileFilter(new LogFileFilter()); - fileChooser.addChoosableFileFilter(new MSTypeFileFilter(labels)); - - final String chooserClass = getApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); - - if (chooserClass != null) { - try { - final FileFilter[] existingFilters = fileChooser.getChoosableFileFilters(); - boolean alreadyHasSavedFilter = false; - for (int i = 0; i < existingFilters.length; i++) { - final String thisFilter = existingFilters[i].getClass().getCanonicalName(); - if (thisFilter.equals(chooserClass)) { - alreadyHasSavedFilter = true; - fileChooser.setFileFilter(existingFilters[i]); // If set to a new instance the list will contain two! - } - } - - // If it's not one of ours, create a new one and set it, though that almost certainly means we'll throw an exception and clean up the prefs... - if (!alreadyHasSavedFilter) { - final FileFilter savedFilter = (FileFilter) Class.forName(chooserClass).newInstance(); - fileChooser.setFileFilter(savedFilter); - } - } catch (ClassNotFoundException c) { - removeApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); - System.out.println(labels.getString(Text.CLASS_NOT_FOUND) + NAME_OF_LAST_CHOOSER_CLASS + labels.getString(Text.REMOVED_FROM_PROPS)); - } catch (InstantiationException i) { - removeApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); - System.out.println(labels.getString(Text.COULD_NOT_INSTANTIATE_CLASS) + NAME_OF_LAST_CHOOSER_CLASS + labels.getString(Text.REMOVED_FROM_PROPS)); - } catch (IllegalAccessException l) { - removeApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); - System.out.println(labels.getString(Text.COULD_NOT_ACCESS_CLASS) + NAME_OF_LAST_CHOOSER_CLASS + labels.getString(Text.REMOVED_FROM_PROPS)); - } - } - return fileChooser; - } - - private String getApplicationWideProperty(final String key) { - final Properties appWide = new Properties(); - openAppWideProps(appWide); - return appWide.getProperty(key); - } - - private void saveApplicationWideProperty(final String key, final String value) { - FileOutputStream fos = null; - try { - final Properties appWide = new Properties(); - final File appWideFile = openAppWideProps(appWide); - appWide.setProperty(key, value); - fos = new FileOutputStream(appWideFile); - appWide.store(fos, "saved"); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException(labels.getString(Text.IO_ISSUE_SAVING_PROPERTY) + e.getMessage(), e); - } finally { - try { - if (fos != null) { - fos.close(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - - private void removeApplicationWideProperty(final String key) { - FileOutputStream fos = null; - try { - final Properties appWide = new Properties(); - final File appWideFile = openAppWideProps(appWide); - appWide.remove(key); - fos = new FileOutputStream(appWideFile); - appWide.store(fos, "removed"); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException(labels.getString(Text.IO_ISSUE_REMOVING_PROPERTY) + e.getMessage(), e); - } finally { - try { - if (fos != null) { - fos.close(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - - private File openAppWideProps(final Properties appWide) { - File appWideFile; - appWideFile = new File(System.getProperty(Keys.USER_HOME)); - - if (!appWideFile.exists() || !appWideFile.canRead() || !appWideFile.canWrite()) { - System.out.println(labels.getString(Text.HOME_DIRECTORY_NOT_ACCESSIBLE)); - } else { - appWideFile = new File(appWideFile, SETTINGS_DIRECTORY); - } - - if (!appWideFile.exists()) { - FileInputStream fis = null; - try { - if (appWideFile.mkdir()) { - appWideFile = new File(appWideFile, PROPERTIES_FILENAME); - if (appWideFile.createNewFile()) { - fis = new FileInputStream(appWideFile); - appWide.load(fis); - } - } else { - throw new RuntimeException(labels.getString(Text.FAILED_TO_CREATE_DIRECTORY_MESSAGE)); - // This should be passed up to the GUI as a dialog that tells you it can't do what it has to be able to... - } - } catch (IOException e) { - System.out.print(e.getMessage()); - } finally { - try { - if (fis != null) { - fis.close(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } else { - appWideFile = new File(appWideFile, PROPERTIES_FILENAME); - FileInputStream fis = null; - try { - if (!appWideFile.createNewFile()) { - fis = new FileInputStream(appWideFile); - appWide.load(fis); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } finally { - try { - if (fis != null) { - fis.close(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - return appWideFile; - } - - public static void setupWindowKeyBindings(final JFrame window) { - final Action closeWindow = new AbstractAction() { - private static final long serialVersionUID = 1L; - public void actionPerformed(final ActionEvent e) { - final WindowEvent wev = new WindowEvent(window, WindowEvent.WINDOW_CLOSING); - Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev); - } - }; - - boolean isMainApp = false; - if (window instanceof OpenLogViewer) { - isMainApp = true; - } - - // Close any window - if (IS_WINDOWS || IS_LINUX) { - window.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Keys.CONTROL_W), Keys.CLOSE_WINDOW); - } else if (IS_MAC_OS_X) { - window.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Keys.COMMAND_W), Keys.CLOSE_WINDOW); - } - - // Just close the main app window - if (IS_LINUX && isMainApp) { - window.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Keys.CONTROL_Q), Keys.CLOSE_WINDOW); - } - - window.getRootPane().getActionMap().put(Keys.CLOSE_WINDOW, closeWindow); - } - - public void enterFullScreen() { - if (!fullscreen) { - final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - final GraphicsDevice[] device = ge.getScreenDevices(); - - for (int i = 0; i < device.length; i++) { // Cycle through available devices (monitors) looking for device that has center of app - final Rectangle bounds = device[i].getDefaultConfiguration().getBounds(); - final int centerX = (int) Math.round(getBounds().getCenterX()); - final int centerY = (int) Math.round(getBounds().getCenterY()); - final Point center = new Point(centerX, centerY); - if (bounds.contains(center)) { // Found the device (monitor) that contains the center of the app - containingDevice = i; - if (device[containingDevice].isFullScreenSupported()) { - try { - fullscreen = true; // Remember so that we can react accordingly. - saveScreenState(); // Save the current state of things to restore later when exiting fullscreen mode. - setVisible(false); // Hide how the sausage is made! - setJMenuBar(null); // Remove the menu bar for maximum space, load files with the buttons? - dispose(); // Make the JFrame undisplayable so setUndecorated(true) will work! - setUndecorated(true); // Remove the window frame/bezel! - setVisible(true); // Make the JFrame displayable again! + private static final long serialVersionUID = 1L; + + private static final Logger LOG = LogManager.getLogger(OpenLogViewer.class); + + public static final String NEWLINE = System.getProperty(Keys.LINE_SEPARATOR); + + private static final Properties buildInfo = new Properties(); + + private static final String APPLICATION_NAME = OpenLogViewer.class.getSimpleName(); + private static final String SETTINGS_DIRECTORY = "." + APPLICATION_NAME; + + private static final String GIT_DESCRIBE_KEY = "git.commit.id.describe"; + + // TODO localise and refactor these: + private static final String PROPERTIES_FILENAME = "OLVAllProperties.olv"; + + private static final String NAME_OF_LAST_FILE_KEY = "lastFingFile"; + private static final String NAME_OF_LAST_DIR_KEY = "lastFingDir"; + private static final String NAME_OF_LAST_CHOOSER_CLASS = "chooserClass"; + + // Real vars start here, many will probably get ripped out later + private static final int GRAPH_PANEL_WIDTH = 600; + private static final int GRAPH_PANEL_HEIGHT = 420; + + private static final String OS_NAME = System.getProperty(Keys.OS_NAME); + private static final boolean IS_MAC_OS_X = OS_NAME.contains("OS X"); // TN2110 + private static final boolean IS_WINDOWS = OS_NAME.contains("Windows"); + private static final boolean IS_LINUX = OS_NAME.contains("Linux"); + + private static OpenLogViewer mainAppRef; + private static ResourceBundle labels; + + private final String applicationTitle; + private final String applicationVersion; + private final EntireGraphingPanel graphingPanel; + private final FooterPanel footerPanel; + private final OptionFrameV2 optionFrame; + private final PropertiesPane prefFrame; + + private final List properties; + private final JMenuBar menuBar; + private AbstractDecoder decoderInUse; + private boolean fullscreen; + + private int extendedState; + private Point location; + private Dimension size; + private int containingDevice; + + public OpenLogViewer() { + try { + buildInfo.load(getClass().getClassLoader().getResourceAsStream("buildInfo.properties")); + buildInfo.load(getClass().getClassLoader().getResourceAsStream("git.properties")); + } catch (IOException e) { + LOG.error("Uh oh, looks like a hacked copy! UNSUPPORTED VERSION! DO NOT USE!"); + } finally { + String preliminaryVersion = buildInfo.getProperty(GIT_DESCRIBE_KEY); + if (preliminaryVersion == null || "".equals(preliminaryVersion.trim())) { + LOG.error("Application version not found! UNSUPPORTED VERSION! DO NOT USE!"); + applicationVersion = "UNSUPPORTED VERSION! DO NOT USE!"; + buildInfo.setProperty(GIT_DESCRIBE_KEY, applicationVersion); + } else { + applicationVersion = buildInfo.getProperty(GIT_DESCRIBE_KEY); + buildInfo.setProperty(GIT_DESCRIBE_KEY, applicationVersion); + } + } + + applicationTitle = APPLICATION_NAME + " " + applicationVersion; + buildInfo.setProperty("application.title", applicationTitle); + + prefFrame = new PropertiesPane(labels, SETTINGS_DIRECTORY); + properties = new ArrayList<>(); + prefFrame.setProperties(properties); + + footerPanel = new FooterPanel(labels); + optionFrame = new OptionFrameV2(labels); + graphingPanel = new EntireGraphingPanel(labels); + graphingPanel.setPreferredSize(new Dimension(GRAPH_PANEL_WIDTH, GRAPH_PANEL_HEIGHT)); + + setDefaultCloseOperation(EXIT_ON_CLOSE); + setTitle(applicationTitle); + setLayout(new BorderLayout()); + setFocusable(true); + + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(graphingPanel, BorderLayout.CENTER); + mainPanel.add(footerPanel, BorderLayout.SOUTH); + add(mainPanel, BorderLayout.CENTER); + + final JMenuItem openFileMenuItem = new JMenuItem(labels.getString(Text.FILE_MENU_ITEM_OPEN_NAME)); + openFileMenuItem.setName(Text.FILE_MENU_ITEM_OPEN_NAME); + openFileMenuItem.addActionListener(e -> openChosenFile()); + + final JMenuItem reloadFileMenuItem = new JMenuItem(labels.getString(Text.FILE_MENU_ITEM_RELOAD_NAME)); + reloadFileMenuItem.setName(Text.FILE_MENU_ITEM_RELOAD_NAME); + reloadFileMenuItem.addActionListener(e -> openLastFile()); + + final JMenuItem quitFileMenuItem = new JMenuItem(labels.getString(Text.FILE_MENU_ITEM_QUIT_NAME)); + quitFileMenuItem.setName(Text.FILE_MENU_ITEM_QUIT_NAME); + quitFileMenuItem.addActionListener(e -> OpenLogViewer.getInstance().quit()); + + final JMenuItem fullScreenViewMenuItem = new JMenuItem(labels.getString(Text.VIEW_MENU_ITEM_FULL_SCREEN_NAME)); + fullScreenViewMenuItem.setName(Text.VIEW_MENU_ITEM_FULL_SCREEN_NAME); + fullScreenViewMenuItem.addActionListener(e -> enterFullScreen()); + + final JMenuItem scaleAndColorViewMenuItem = new JMenuItem(labels.getString(Text.VIEW_MENU_ITEM_SCALE_AND_COLOR_NAME)); + scaleAndColorViewMenuItem.setName(Text.VIEW_MENU_ITEM_SCALE_AND_COLOR_NAME); + scaleAndColorViewMenuItem.addActionListener(e -> prefFrame.setVisible(true)); + + final JMenuItem fieldsAndDivisionsViewMenuItem = new JMenuItem(labels.getString(Text.VIEW_MENU_ITEM_FIELDS_AND_DIVISIONS_NAME)); + fieldsAndDivisionsViewMenuItem.setName(Text.VIEW_MENU_ITEM_FIELDS_AND_DIVISIONS_NAME); + fieldsAndDivisionsViewMenuItem.addActionListener(e -> optionFrame.setVisible(true)); + + final JMenuItem aboutMenuItem = new JMenuItem(labels.getString(Text.HELP_MENU_ITEM_ABOUT_NAME)); + aboutMenuItem.setName(Text.HELP_MENU_ITEM_ABOUT_NAME); + aboutMenuItem.addActionListener(e -> AboutFrame.show(buildInfo)); + + /* + * 13 January 2012 Had Chick-fil-A #1 meal with no pickle and Dr Pepper for lunch. + * Dr Pepper with no period. "Dude didn't even get his degree." Either that or he is British. + * 1 November 2011 Migrated Gufi's menu from the pointless class it's in to here. + * 22 October 2011 Left Gufi's menu in place for future dev's enjoyment. + * + * 5 February 2011 meal for the night DO NOT EDIT MENU! + * Sesame chicken alacarte + * chicken lo mein alacarte + * orange chicken x2 + */ + + final JMenu fileMenu = new JMenu(labels.getString(Text.FILE_MENU_NAME)); + fileMenu.setName(Text.FILE_MENU_NAME); + fileMenu.add(openFileMenuItem); + fileMenu.add(reloadFileMenuItem); + if (!IS_MAC_OS_X) { + fileMenu.add(quitFileMenuItem); + } + + final JMenu viewMenu = new JMenu(labels.getString(Text.VIEW_MENU_NAME)); + viewMenu.setName(Text.VIEW_MENU_NAME); + viewMenu.add(fullScreenViewMenuItem); + viewMenu.add(scaleAndColorViewMenuItem); + viewMenu.add(fieldsAndDivisionsViewMenuItem); + + final JMenu helpMenu = new JMenu(labels.getString(Text.HELP_MENU_NAME)); + helpMenu.setName(Text.HELP_MENU_NAME); + helpMenu.add(aboutMenuItem); + + menuBar = new JMenuBar(); + menuBar.add(fileMenu); + menuBar.add(viewMenu); + if (IS_MAC_OS_X) { + new MacOSAboutHandler(buildInfo); + } else { + menuBar.add(helpMenu); + } + setJMenuBar(menuBar); + + //Listener stuff + addComponentListener(graphingPanel); + setupWindowKeyBindings(this); + + setName(applicationTitle); + + pack(); + + setVisible(true); + } + + /** + * The entry point of OLV! + * + * @param args the command line arguments + */ + public static void main(final String[] args) { + EventQueue.invokeLater(() -> { + final Locale currentLocale = Locale.getDefault(); + + labels = ResourceBundle.getBundle(OpenLogViewer.class.getPackage().getName() + ".Labels", currentLocale); + + final String lookAndFeel; + final String systemLookAndFeel = UIManager.getSystemLookAndFeelClassName(); + if (IS_MAC_OS_X) { + System.setProperty(Keys.APPLE_LAF_USE_SCREEN_MENU_BAR, Boolean.TRUE.toString()); + } + lookAndFeel = systemLookAndFeel; + + try { + UIManager.setLookAndFeel(lookAndFeel); + } catch (UnsupportedLookAndFeelException e) { + LOG.error(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_ONE), e); + } catch (ClassNotFoundException e) { + LOG.error(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_TWO), e); + } catch (InstantiationException e) { + LOG.error(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_THREE), e); + } catch (IllegalAccessException e) { + LOG.error(labels.getString(Text.LOOK_AND_FEEL_EXCEPTION_MESSAGE_FOUR), e); + } + + mainAppRef = new OpenLogViewer(); + + if (args.length > 0) { + final File toOpen = new File(args[0]).getAbsoluteFile(); + if (toOpen.exists() && toOpen.isFile()) { + if (args.length > 1) { + LOG.error(args.length + labels.getString(Text.TOO_MANY_ARGUMENTS) + args[0]); + } else { + LOG.error(labels.getString(Text.ATTEMPTING_TO_OPEN_FILE) + args[0]); + } + final FileFilter ms = new MSTypeFileFilter(labels); + final FileFilter fe = new FreeEMSFileFilter(labels); + if (fe.accept(toOpen) || ms.accept(toOpen)) { + mainAppRef.openFile(toOpen, mainAppRef.generateChooser()); + } else { + LOG.error(labels.getString(Text.FILE_TYPE_NOT_SUPPORTED) + args[0]); + mainAppRef.quit(); + } + } else { + LOG.error(labels.getString(Text.FILE_ARGUMENT_NOT_GOOD) + args[0]); + mainAppRef.quit(); + } + } + }); + } + + public static void setupWindowKeyBindings(final JFrame window) { + final Action closeWindow = new AbstractAction() { + private static final long serialVersionUID = 1L; + + public void actionPerformed(final ActionEvent e) { + final WindowEvent wev = new WindowEvent(window, WindowEvent.WINDOW_CLOSING); + Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev); + } + }; + + boolean isMainApp = false; + if (window instanceof OpenLogViewer) { + isMainApp = true; + } + + // Close any window + if (IS_WINDOWS || IS_LINUX) { + window.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Keys.CONTROL_W), Keys.CLOSE_WINDOW); + } else if (IS_MAC_OS_X) { + window.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Keys.COMMAND_W), Keys.CLOSE_WINDOW); + } + + // Just close the main app window + if (IS_LINUX && isMainApp) { + window.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Keys.CONTROL_Q), Keys.CLOSE_WINDOW); + } + + window.getRootPane().getActionMap().put(Keys.CLOSE_WINDOW, closeWindow); + } + + /** + * Returns the reference to this instance, it is meant to be a method to make getting the main frame simpler + * + * @return this instance + */ + public static OpenLogViewer getInstance() { + return mainAppRef; + } + + public void quit() { + final WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING); + Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev); + } + + public void openChosenFile() { + final JFileChooser fileChooser = generateChooser(); + final int acceptValue = fileChooser.showOpenDialog(this); + if (acceptValue == JFileChooser.APPROVE_OPTION) { + final File fileToOpen = fileChooser.getSelectedFile(); + if (!openFile(fileToOpen, fileChooser)) { + JOptionPane.showMessageDialog(mainAppRef, labels.getObject(Text.OPEN_FILE_ERROR_MESSAGE) + + NEWLINE + fileToOpen.getAbsolutePath(), + labels.getString(Text.OPEN_FILE_ERROR_TITLE), + JOptionPane.ERROR_MESSAGE); + } + } + } + + public void openLastFile() { + final String lastFingFile = getApplicationWideProperty(NAME_OF_LAST_FILE_KEY); + final String chooserClass = getApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); + if (chooserClass != null && lastFingFile != null) { + final File fileToOpen = new File(lastFingFile); + final JFileChooser fileChooser = generateChooser(); + if (!openFile(fileToOpen, fileChooser)) { + JOptionPane.showMessageDialog(mainAppRef, labels.getObject(Text.OPEN_LAST_FILE_ERROR_MESSAGE) + + NEWLINE + fileToOpen.getAbsolutePath(), + labels.getString(Text.OPEN_LAST_FILE_ERROR_TITLE), + JOptionPane.ERROR_MESSAGE); + } + } else { + JOptionPane.showMessageDialog(mainAppRef, labels.getObject(Text.OPEN_LAST_FILE_MISSING_PROPERTY_MESSAGE), + labels.getString(Text.OPEN_LAST_FILE_MISSING_PROPERTY_TITLE), + JOptionPane.ERROR_MESSAGE); + } + } + + public boolean openFile(final File fileToOpen, final JFileChooser fileChooser) { + if (fileToOpen.exists()) { + if (decoderInUse != null) { + // Clear out all references to data that we don't need and thereby ensure that we have lots of memory free for data we're about to gather! + final GenericLog logInUse = decoderInUse.getDecodedLog(); + if (logInUse != null) { + logInUse.clearOut(); // This is the wrong approach. The correct approach is to reuse the object, try that next... + } + decoderInUse = null; + setLog(null); + } // else haven't read in a log yet. + + setTitle(applicationTitle + " - " + fileToOpen.getName()); + saveApplicationWideProperty(NAME_OF_LAST_DIR_KEY, fileToOpen.getParent()); + saveApplicationWideProperty(NAME_OF_LAST_FILE_KEY, fileToOpen.getPath()); + saveApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS, fileChooser.getFileFilter().getClass().getCanonicalName()); + + if (FileExtensions.BIN.equals(FileExtensions.getByExtension(Utilities.getExtension(fileToOpen))) + || FileExtensions.LA.equals(FileExtensions.getByExtension(Utilities.getExtension(fileToOpen))) + || (fileChooser.getFileFilter() instanceof FreeEMSFileFilter)) { + decoderInUse = new FreeEMSBin(fileToOpen, labels); + } else { + decoderInUse = new CSVTypeLog(fileToOpen, labels); + } + return true; + } else { + setTitle(applicationTitle); + return false; + } + } + + public JFileChooser generateChooser() { + final JFileChooser fileChooser = new JFileChooser(); + final String lastFingFile = getApplicationWideProperty(NAME_OF_LAST_FILE_KEY); + + if (lastFingFile != null) { + fileChooser.setSelectedFile(new File(lastFingFile)); + } else { + final String lastFingDir = getApplicationWideProperty(NAME_OF_LAST_DIR_KEY); + if (lastFingDir != null) { + fileChooser.setCurrentDirectory(new File(lastFingDir)); + } + } + + fileChooser.addChoosableFileFilter(new FreeEMSFileFilter(labels)); + fileChooser.addChoosableFileFilter(new FreeEMSBinFileFilter()); + fileChooser.addChoosableFileFilter(new FreeEMSLAFileFilter()); + fileChooser.addChoosableFileFilter(new CSVFileFilter()); + fileChooser.addChoosableFileFilter(new LogFileFilter()); + fileChooser.addChoosableFileFilter(new MSTypeFileFilter(labels)); + + final String chooserClass = getApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); + + if (chooserClass != null) { + try { + final FileFilter[] existingFilters = fileChooser.getChoosableFileFilters(); + boolean alreadyHasSavedFilter = false; + for (FileFilter existingFilter : existingFilters) { + final String thisFilter = existingFilter.getClass().getCanonicalName(); + if (thisFilter.equals(chooserClass)) { + alreadyHasSavedFilter = true; + fileChooser.setFileFilter(existingFilter); // If set to a new instance the list will contain two! + } + } + + // If it's not one of ours, create a new one and set it, though that almost certainly means we'll throw an exception and clean up the prefs... + if (!alreadyHasSavedFilter) { + final FileFilter savedFilter = (FileFilter) Class.forName(chooserClass).newInstance(); + fileChooser.setFileFilter(savedFilter); + } + } catch (ClassNotFoundException c) { + removeApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); + LOG.error(labels.getString(Text.CLASS_NOT_FOUND) + NAME_OF_LAST_CHOOSER_CLASS + labels.getString(Text.REMOVED_FROM_PROPS)); + } catch (InstantiationException i) { + removeApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); + LOG.error(labels.getString(Text.COULD_NOT_INSTANTIATE_CLASS) + NAME_OF_LAST_CHOOSER_CLASS + labels.getString(Text.REMOVED_FROM_PROPS)); + } catch (IllegalAccessException l) { + removeApplicationWideProperty(NAME_OF_LAST_CHOOSER_CLASS); + LOG.error(labels.getString(Text.COULD_NOT_ACCESS_CLASS) + NAME_OF_LAST_CHOOSER_CLASS + labels.getString(Text.REMOVED_FROM_PROPS)); + } + } + return fileChooser; + } + + private String getApplicationWideProperty(final String key) { + final Properties appWide = new Properties(); + openAppWideProps(appWide); + return appWide.getProperty(key); + } + + private void saveApplicationWideProperty(final String key, final String value) { + FileOutputStream fos = null; + try { + final Properties appWide = new Properties(); + final File appWideFile = openAppWideProps(appWide); + appWide.setProperty(key, value); + fos = new FileOutputStream(appWideFile); + appWide.store(fos, "saved"); + } catch (IOException e) { + LOG.error(e); + throw new RuntimeException(labels.getString(Text.IO_ISSUE_SAVING_PROPERTY) + e.getMessage(), e); + } finally { + try { + if (fos != null) { + fos.close(); + } + } catch (IOException e) { + LOG.error(e); + } + } + } + + private void removeApplicationWideProperty(final String key) { + FileOutputStream fos = null; + try { + final Properties appWide = new Properties(); + final File appWideFile = openAppWideProps(appWide); + appWide.remove(key); + fos = new FileOutputStream(appWideFile); + appWide.store(fos, "removed"); + } catch (IOException e) { + LOG.error(e); + throw new RuntimeException(labels.getString(Text.IO_ISSUE_REMOVING_PROPERTY) + e.getMessage(), e); + } finally { + try { + if (fos != null) { + fos.close(); + } + } catch (IOException e) { + LOG.error(e); + } + } + } + + private File openAppWideProps(final Properties appWide) { + File appWideFile; + appWideFile = new File(System.getProperty(Keys.USER_HOME)); + + if (!appWideFile.exists() || !appWideFile.canRead() || !appWideFile.canWrite()) { + LOG.error(labels.getString(Text.HOME_DIRECTORY_NOT_ACCESSIBLE)); + } else { + appWideFile = new File(appWideFile, SETTINGS_DIRECTORY); + } + + if (!appWideFile.exists()) { + FileInputStream fis = null; + try { + if (appWideFile.mkdir()) { + appWideFile = new File(appWideFile, PROPERTIES_FILENAME); + if (appWideFile.createNewFile()) { + fis = new FileInputStream(appWideFile); + appWide.load(fis); + } + } else { + throw new RuntimeException(labels.getString(Text.FAILED_TO_CREATE_DIRECTORY_MESSAGE)); + // This should be passed up to the GUI as a dialog that tells you it can't do what it has to be able to... + } + } catch (IOException e) { + LOG.error(e); + } finally { + try { + if (fis != null) { + fis.close(); + } + } catch (IOException e) { + LOG.error(e); + } + } + } else { + appWideFile = new File(appWideFile, PROPERTIES_FILENAME); + FileInputStream fis = null; + try { + if (!appWideFile.createNewFile()) { + fis = new FileInputStream(appWideFile); + appWide.load(fis); + } + } catch (IOException e) { + LOG.error(e); + } finally { + try { + if (fis != null) { + fis.close(); + } + } catch (IOException e) { + LOG.error(e); + } + } + } + return appWideFile; + } + + public void enterFullScreen() { + if (!fullscreen) { + final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice[] device = ge.getScreenDevices(); + + for (int i = 0; i < device.length; i++) { // Cycle through available devices (monitors) looking for device that has center of app + final Rectangle bounds = device[i].getDefaultConfiguration().getBounds(); + final int centerX = (int) Math.round(getBounds().getCenterX()); + final int centerY = (int) Math.round(getBounds().getCenterY()); + final Point center = new Point(centerX, centerY); + if (bounds.contains(center)) { // Found the device (monitor) that contains the center of the app + containingDevice = i; + if (device[containingDevice].isFullScreenSupported()) { + try { + fullscreen = true; // Remember so that we can react accordingly. + saveScreenState(); // Save the current state of things to restore later when exiting fullscreen mode. + setVisible(false); // Hide how the sausage is made! + setJMenuBar(null); // Remove the menu bar for maximum space, load files with the buttons? + dispose(); // Make the JFrame undisplayable so setUndecorated(true) will work! + setUndecorated(true); // Remove the window frame/bezel! + setVisible(true); // Make the JFrame displayable again! // setResizable(false); // Fred: doesn't make sense and could be dangerous, according to oracle. - // Ben: Removed setResizable(false) because it causes GNOME menu bar - // and GNOME task bar to show in front of the app! - device[containingDevice].setFullScreenWindow(this); - validate(); // Required after rearranging component hierarchy - toFront(); // Might as well - requestFocusInWindow(); // Put keyboard focus here so toggling fullscreen works - graphingPanel.moveGraphDueToResize(); // Done so centering still works on Mac - } catch (IllegalComponentStateException e) { - e.printStackTrace(); - System.out.println(labels.getString(Text.FAILED_TO_GO_FULLSCREEN_MESSAGE)); - fullscreen = false; - } - } else { - System.out.println(labels.getString(Text.CANT_GO_FULLSCREEN_MESSAGE)); - } - } - } - } - } - - public void exitFullScreen() { - if (fullscreen) { - fullscreen = false; - final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - final GraphicsDevice[] device = ge.getScreenDevices(); - // Do the reverse of what we did to put it into full screen! - device[containingDevice].setFullScreenWindow(null); // Exit full screen - dispose(); // Make the JFrame undisplayable so setUndecorated(false) will work - setUndecorated(false); // Restore the window frame/bezel - setJMenuBar(menuBar); // Remove the menu bar - validate(); // Required after rearranging component hierarchy - restoreScreenState(); // Size and place the window where it was before - setVisible(true); // Make the JFrame displayable again - requestFocusInWindow(); // Put keyboard focus here so toggling fullscreen works - graphingPanel.moveGraphDueToResize(); // Done so centering still works on Mac - } - } - - public void toggleFullScreen() { - if (fullscreen) { - exitFullScreen(); - } else { - enterFullScreen(); - } - } - - private void saveScreenState() { - extendedState = getExtendedState(); - location = getLocation(); - size = getSize(); - } - - private void restoreScreenState() { - setExtendedState(extendedState); - setLocation(location); - setSize(size); - } - - public void setLog(final GenericLog genericLog) { - graphingPanel.setLog(genericLog); - } - - public void defaultBrowserNotFound() { - final Object message = labels.getObject(Text.DEFAULT_BROWSER_ERROR_MESSAGE); - final String title = labels.getString(Text.DEFAULT_BROWSER_ERROR_TITLE); - JOptionPane.showMessageDialog(mainAppRef, message, title, JOptionPane.ERROR_MESSAGE); // DIRTY - } - - // All of the references below are indicators of bad design, marking with DIRTY: - - /** - * Returns the reference to this instance, it is meant to be a method to make getting the main frame simpler - * @return this instance - */ - public static OpenLogViewer getInstance() { - return mainAppRef; - } - - public NavBarPanel getNavBarPanel() { - return footerPanel.getNavBarPanel(); - } - - public EntireGraphingPanel getEntireGraphingPanel() { - return graphingPanel; - } - - public MultiGraphLayeredPane getMultiGraphLayeredPane() { - return graphingPanel.getMultiGraphLayeredPane(); - } - - public OptionFrameV2 getOptionFrame() { - return optionFrame; - } - - public PropertiesPane getPropertyPane() { - return prefFrame; - } - - public List getProperties() { - return properties; - } + // Ben: Removed setResizable(false) because it causes GNOME menu bar + // and GNOME task bar to show in front of the app! + device[containingDevice].setFullScreenWindow(this); + validate(); // Required after rearranging component hierarchy + toFront(); // Might as well + requestFocusInWindow(); // Put keyboard focus here so toggling fullscreen works + graphingPanel.moveGraphDueToResize(); // Done so centering still works on Mac + } catch (IllegalComponentStateException e) { + LOG.error(e); + LOG.error(labels.getString(Text.FAILED_TO_GO_FULLSCREEN_MESSAGE)); + fullscreen = false; + } + } else { + LOG.error(labels.getString(Text.CANT_GO_FULLSCREEN_MESSAGE)); + } + } + } + } + } + + public void exitFullScreen() { + if (fullscreen) { + fullscreen = false; + final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice[] device = ge.getScreenDevices(); + // Do the reverse of what we did to put it into full screen! + device[containingDevice].setFullScreenWindow(null); // Exit full screen + dispose(); // Make the JFrame undisplayable so setUndecorated(false) will work + setUndecorated(false); // Restore the window frame/bezel + setJMenuBar(menuBar); // Remove the menu bar + validate(); // Required after rearranging component hierarchy + restoreScreenState(); // Size and place the window where it was before + setVisible(true); // Make the JFrame displayable again + requestFocusInWindow(); // Put keyboard focus here so toggling fullscreen works + graphingPanel.moveGraphDueToResize(); // Done so centering still works on Mac + } + } + + public void toggleFullScreen() { + if (fullscreen) { + exitFullScreen(); + } else { + enterFullScreen(); + } + } + + private void saveScreenState() { + extendedState = getExtendedState(); + location = getLocation(); + size = getSize(); + } + + private void restoreScreenState() { + setExtendedState(extendedState); + setLocation(location); + setSize(size); + } + + public void setLog(final GenericLog genericLog) { + graphingPanel.setLog(genericLog); + } + + // All of the references below are indicators of bad design, marking with DIRTY: + + public void defaultBrowserNotFound() { + final Object message = labels.getObject(Text.DEFAULT_BROWSER_ERROR_MESSAGE); + final String title = labels.getString(Text.DEFAULT_BROWSER_ERROR_TITLE); + JOptionPane.showMessageDialog(mainAppRef, message, title, JOptionPane.ERROR_MESSAGE); // DIRTY + } + + public NavBarPanel getNavBarPanel() { + return footerPanel.getNavBarPanel(); + } + + public EntireGraphingPanel getEntireGraphingPanel() { + return graphingPanel; + } + + public MultiGraphLayeredPane getMultiGraphLayeredPane() { + return graphingPanel.getMultiGraphLayeredPane(); + } + + public OptionFrameV2 getOptionFrame() { + return optionFrame; + } + + public PropertiesPane getPropertyPane() { + return prefFrame; + } + + public List getProperties() { + return properties; + } } diff --git a/src/main/java/org/diyefi/openlogviewer/coloring/InitialLineColoring.java b/src/main/java/org/diyefi/openlogviewer/coloring/InitialLineColoring.java index 6ab15c9..00a590b 100644 --- a/src/main/java/org/diyefi/openlogviewer/coloring/InitialLineColoring.java +++ b/src/main/java/org/diyefi/openlogviewer/coloring/InitialLineColoring.java @@ -30,6 +30,7 @@ /** * InitialLineColoring is used to provide the coloring for the GenericDataElements. * The colors provided should be the most contrasting colors possible. + * * @author Ben Fenner */ public enum InitialLineColoring { @@ -50,7 +51,7 @@ public enum InitialLineColoring { private final Color bookEndRed = Color.getHSBColor(ALMOST_ONE, 1.0F, 1.0F); private InitialLineColoring() { - colorList = new LinkedList(); + colorList = new LinkedList<>(); colorList.add(0, bookEndRed); // Seed with high value red } diff --git a/src/main/java/org/diyefi/openlogviewer/decoder/CSVTypeLog.java b/src/main/java/org/diyefi/openlogviewer/decoder/CSVTypeLog.java index d21c598..c48e122 100644 --- a/src/main/java/org/diyefi/openlogviewer/decoder/CSVTypeLog.java +++ b/src/main/java/org/diyefi/openlogviewer/decoder/CSVTypeLog.java @@ -81,34 +81,35 @@ public final void run() { * @throws IOException */ protected final void decodeLog() throws IOException { - final Scanner scan = new Scanner(new BufferedReader(new FileReader(getLogFile()))); - final String delimiter = scanForDelimiter(); + try (Scanner scan = new Scanner(new BufferedReader(new FileReader(getLogFile())))) { + final String delimiter = scanForDelimiter(); - String[] splitLine; - String[] headers = new String[1]; + String[] splitLine; + String[] headers = new String[1]; - int finalAndInitialLength = Utilities.countBytes(getLogFile(), (byte) '\n'); + int finalAndInitialLength = Utilities.countBytes(getLogFile(), (byte) '\n'); - String line = ""; - boolean headerSet = false; - while (scan.hasNextLine() && !headerSet) { - line = scan.nextLine(); - splitLine = line.split(delimiter); + String line = ""; + boolean headerSet = false; + while (scan.hasNextLine() && !headerSet) { + line = scan.nextLine(); + splitLine = line.split(delimiter); - if (splitLine.length == fieldCount) { - headers = splitLine; - this.setDecodedLog(new GenericLog(splitLine, finalAndInitialLength, LOAD_FACTOR, labels)); - headerSet = true; + if (splitLine.length == fieldCount) { + headers = splitLine; + this.setDecodedLog(new GenericLog(splitLine, finalAndInitialLength, LOAD_FACTOR, labels)); + headerSet = true; + } } - } - while (scan.hasNextLine()) { - line = scan.nextLine(); - splitLine = line.split(delimiter); - this.getDecodedLog().incrementPosition(); - if (splitLine.length == fieldCount) { - for (int x = 0; x < splitLine.length; x++) { - this.getDecodedLog().addValue(headers[x], Double.parseDouble(splitLine[x])); + while (scan.hasNextLine()) { + line = scan.nextLine(); + splitLine = line.split(delimiter); + this.getDecodedLog().incrementPosition(); + if (splitLine.length == fieldCount) { + for (int x = 0; x < splitLine.length; x++) { + this.getDecodedLog().addValue(headers[x], Double.parseDouble(splitLine[x])); + } } } } diff --git a/src/main/java/org/diyefi/openlogviewer/filefilters/CSVFileFilter.java b/src/main/java/org/diyefi/openlogviewer/filefilters/CSVFileFilter.java index e83a030..9b2feef 100644 --- a/src/main/java/org/diyefi/openlogviewer/filefilters/CSVFileFilter.java +++ b/src/main/java/org/diyefi/openlogviewer/filefilters/CSVFileFilter.java @@ -22,26 +22,26 @@ */ package org.diyefi.openlogviewer.filefilters; -import java.io.File; -import javax.swing.filechooser.FileFilter; - import org.diyefi.openlogviewer.FileExtensions; import org.diyefi.openlogviewer.utils.Utilities; +import javax.swing.filechooser.FileFilter; +import java.io.File; + public class CSVFileFilter extends FileFilter { - @Override - public final String getDescription() { - return FileExtensions.STAR_DOT + FileExtensions.CSV; - } + @Override + public final String getDescription() { + return FileExtensions.STAR_DOT.getExtension() + FileExtensions.CSV.getExtension(); + } - @Override - public final boolean accept(final File file) { - if (file.isDirectory()) { - return true; - } + @Override + public final boolean accept(final File file) { + if (file.isDirectory()) { + return true; + } - final String extension = Utilities.getExtension(file); + final String extension = Utilities.getExtension(file); - return FileExtensions.CSV.equals(extension); - } + return FileExtensions.CSV.equals(FileExtensions.getByExtension(extension)); + } } diff --git a/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSBinFileFilter.java b/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSBinFileFilter.java index f1a2a49..3bff6d8 100644 --- a/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSBinFileFilter.java +++ b/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSBinFileFilter.java @@ -23,26 +23,26 @@ package org.diyefi.openlogviewer.filefilters; -import java.io.File; -import javax.swing.filechooser.FileFilter; - import org.diyefi.openlogviewer.FileExtensions; import org.diyefi.openlogviewer.utils.Utilities; +import javax.swing.filechooser.FileFilter; +import java.io.File; + public class FreeEMSBinFileFilter extends FileFilter { - @Override - public final String getDescription() { - return FileExtensions.STAR_DOT + FileExtensions.BIN; - } + @Override + public final String getDescription() { + return FileExtensions.STAR_DOT.getExtension() + FileExtensions.BIN.getExtension(); + } - @Override - public final boolean accept(final File file) { - if (file.isDirectory()) { - return true; - } + @Override + public final boolean accept(final File file) { + if (file.isDirectory()) { + return true; + } - final String extension = Utilities.getExtension(file); + final String extension = Utilities.getExtension(file); - return FileExtensions.BIN.equals(extension); - } + return FileExtensions.BIN.equals(FileExtensions.getByExtension(extension)); + } } diff --git a/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSFileFilter.java b/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSFileFilter.java index fcfca3e..ad17632 100644 --- a/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSFileFilter.java +++ b/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSFileFilter.java @@ -52,9 +52,9 @@ public final boolean accept(final File file) { final String extension = Utilities.getExtension(file); - if (FileExtensions.BIN.equals(extension)) { + if (FileExtensions.BIN.equals(FileExtensions.getByExtension(extension))) { return true; - } else if (FileExtensions.LA.equals(extension)) { + } else if (FileExtensions.LA.equals(FileExtensions.getByExtension(extension))) { return true; } diff --git a/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSLAFileFilter.java b/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSLAFileFilter.java index 54ff3ff..4ffa796 100644 --- a/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSLAFileFilter.java +++ b/src/main/java/org/diyefi/openlogviewer/filefilters/FreeEMSLAFileFilter.java @@ -23,26 +23,26 @@ package org.diyefi.openlogviewer.filefilters; -import java.io.File; -import javax.swing.filechooser.FileFilter; - import org.diyefi.openlogviewer.FileExtensions; import org.diyefi.openlogviewer.utils.Utilities; +import javax.swing.filechooser.FileFilter; +import java.io.File; + public class FreeEMSLAFileFilter extends FileFilter { - @Override - public final String getDescription() { - return FileExtensions.STAR_DOT + FileExtensions.LA; - } + @Override + public final String getDescription() { + return FileExtensions.STAR_DOT.getExtension() + FileExtensions.LA.getExtension(); + } - @Override - public final boolean accept(final File file) { - if (file.isDirectory()) { - return true; - } + @Override + public final boolean accept(final File file) { + if (file.isDirectory()) { + return true; + } - final String extension = Utilities.getExtension(file); + final String extension = Utilities.getExtension(file); - return FileExtensions.LA.equals(extension); - } + return FileExtensions.LA.equals(FileExtensions.getByExtension(extension)); + } } diff --git a/src/main/java/org/diyefi/openlogviewer/filefilters/LogFileFilter.java b/src/main/java/org/diyefi/openlogviewer/filefilters/LogFileFilter.java index bb5362a..20e5087 100644 --- a/src/main/java/org/diyefi/openlogviewer/filefilters/LogFileFilter.java +++ b/src/main/java/org/diyefi/openlogviewer/filefilters/LogFileFilter.java @@ -22,26 +22,26 @@ */ package org.diyefi.openlogviewer.filefilters; -import java.io.File; -import javax.swing.filechooser.FileFilter; - import org.diyefi.openlogviewer.FileExtensions; import org.diyefi.openlogviewer.utils.Utilities; +import javax.swing.filechooser.FileFilter; +import java.io.File; + public class LogFileFilter extends FileFilter { - @Override - public final String getDescription() { - return FileExtensions.STAR_DOT + FileExtensions.LOG; - } + @Override + public final String getDescription() { + return FileExtensions.STAR_DOT.getExtension() + FileExtensions.LOG.getExtension(); + } - @Override - public final boolean accept(final File file) { - if (file.isDirectory()) { - return true; - } + @Override + public final boolean accept(final File file) { + if (file.isDirectory()) { + return true; + } - final String extension = Utilities.getExtension(file); + final String extension = Utilities.getExtension(file); - return FileExtensions.LOG.equals(extension); - } + return FileExtensions.LOG.getExtension().equals(extension); + } } diff --git a/src/main/java/org/diyefi/openlogviewer/filefilters/MSTypeFileFilter.java b/src/main/java/org/diyefi/openlogviewer/filefilters/MSTypeFileFilter.java index 0995b26..415a927 100644 --- a/src/main/java/org/diyefi/openlogviewer/filefilters/MSTypeFileFilter.java +++ b/src/main/java/org/diyefi/openlogviewer/filefilters/MSTypeFileFilter.java @@ -53,11 +53,11 @@ public final boolean accept(final File file) { if (FileExtensions.LOG.equals(extension)) { return true; - } else if (FileExtensions.CSV.equals(extension)) { + } else if (FileExtensions.CSV.equals(FileExtensions.getByExtension(extension))) { return true; - } else if (FileExtensions.XLS.equals(extension)) { + } else if (FileExtensions.XLS.equals(FileExtensions.getByExtension(extension))) { return true; - } else if (FileExtensions.MSL.equals(extension)) { + } else if (FileExtensions.MSL.equals(FileExtensions.getByExtension(extension))) { return true; } diff --git a/src/main/java/org/diyefi/openlogviewer/genericlog/GenericDataElement.java b/src/main/java/org/diyefi/openlogviewer/genericlog/GenericDataElement.java index 5ebd3f0..86e07e5 100644 --- a/src/main/java/org/diyefi/openlogviewer/genericlog/GenericDataElement.java +++ b/src/main/java/org/diyefi/openlogviewer/genericlog/GenericDataElement.java @@ -31,6 +31,8 @@ import java.io.IOException; import java.io.Serializable; import java.util.Arrays; +import java.util.Objects; +import java.util.stream.IntStream; import org.diyefi.openlogviewer.Keys; import org.diyefi.openlogviewer.coloring.InitialLineColoring; @@ -170,6 +172,20 @@ public int compareTo(final GenericDataElement otherGDE) { return this.getName().compareToIgnoreCase(otherGDE.getName()); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GenericDataElement that = (GenericDataElement) o; + return Objects.equals(name.toLowerCase(), that.name.toLowerCase()); + } + + @Override + public int hashCode() { + + return Objects.hash(name.toLowerCase()); + } + @Override public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (flavor.equals(dataFlavor[0])) { @@ -190,12 +206,8 @@ public DataFlavor[] getTransferDataFlavors() { @Override public boolean isDataFlavorSupported(final DataFlavor flavor) { - for (int i = 0; i < dataFlavor.length; i++) { - if (flavor.equals(dataFlavor[i])) { - return true; - } - } - return false; + return IntStream.range(0, dataFlavor.length) + .anyMatch(i -> flavor.equals(dataFlavor[i])); } /** diff --git a/src/main/java/org/diyefi/openlogviewer/graphing/GraphPositionPanel.java b/src/main/java/org/diyefi/openlogviewer/graphing/GraphPositionPanel.java index 627f11f..b34cebe 100644 --- a/src/main/java/org/diyefi/openlogviewer/graphing/GraphPositionPanel.java +++ b/src/main/java/org/diyefi/openlogviewer/graphing/GraphPositionPanel.java @@ -179,7 +179,7 @@ private void paintPositionData(final Graphics2D g2d, final boolean zoomedOut) { String positionDataString; if (majorGraduationSpacing > TENTHS_DISPLAY_THRESHOLD) { - final BigDecimal positionData = new BigDecimal(nextPositionMarker); + final BigDecimal positionData = BigDecimal.valueOf(nextPositionMarker); positionDataString = positionData.toPlainString(); } else if (majorGraduationSpacing > HUNDRETHS_DISPLAY_THRESHOLD) { positionDataString = MathUtils.roundDecimalPlaces(nextPositionMarker, 1); diff --git a/src/main/java/org/diyefi/openlogviewer/graphing/InfoPanel.java b/src/main/java/org/diyefi/openlogviewer/graphing/InfoPanel.java index 5d44f9f..8c335af 100644 --- a/src/main/java/org/diyefi/openlogviewer/graphing/InfoPanel.java +++ b/src/main/java/org/diyefi/openlogviewer/graphing/InfoPanel.java @@ -22,171 +22,169 @@ */ package org.diyefi.openlogviewer.graphing; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.util.ResourceBundle; - -import javax.swing.JPanel; - import org.diyefi.openlogviewer.OpenLogViewer; import org.diyefi.openlogviewer.Text; import org.diyefi.openlogviewer.genericlog.GenericLog; import org.diyefi.openlogviewer.utils.MathUtils; +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.util.ResourceBundle; + public class InfoPanel extends JPanel implements MouseMotionListener, MouseListener { - private static final long serialVersionUID = 1L; - - private static final int LEFT_MARGIN_OFFSET = 10; - private static final int ONE_TEXTUAL_HEIGHT = 20; - private static final int FONT_SIZE = 12; - private static final int INFO_DISPLAY_OFFSET = 4; - private static final Font HOVER_FONT = new Font(Font.MONOSPACED, Font.PLAIN, FONT_SIZE); - - private final ResourceBundle labels; - private final Color vertBar = new Color(255, 255, 255, 100); - private final Color textBackground = new Color(0, 0, 0, 170); - - private GenericLog genLog; - private int xMouseCoord; - private int yMouseCoord; - private boolean shouldDraw; - - public InfoPanel(final ResourceBundle labels) { - this.labels = labels; - setOpaque(false); - } - - @Override - public final void paintComponent(final Graphics g) { - super.paintComponent(g); - - if (!this.getSize().equals(this.getParent().getSize())) { - this.setSize(this.getParent().getSize()); - } - - g.setFont(HOVER_FONT); // Required to keep font consistent when using Mac L&F - if (genLog == null) { - g.setColor(Color.RED); - g.drawString(labels.getString(Text.NO_LOG_LOADED), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT); - } else { - if (genLog.getLogStatus() == GenericLog.LogState.LOG_LOADING) { - g.setColor(Color.red); - g.drawString(labels.getString(Text.LOADING_LOG), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT); - } else if (genLog.getLogStatus() == GenericLog.LogState.LOG_LOADED) { - if (genLog.getLogStatusMessage() != null) { - g.setColor(Color.RED); - g.drawString(labels.getString(Text.DECODER_CRASHED_PART1), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT); - g.drawString(genLog.getLogStatusMessage(), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT * 2); - g.drawString(labels.getString(Text.DECODER_CRASHED_PART2), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT * 3); - } - if (shouldDraw) { - final int dataWidth = getWidestDataWidth(); - final Dimension d = this.getSize(); - final Graphics2D g2d = (Graphics2D) g; - final FontMetrics fm = g.getFontMetrics(g.getFont()); // For getting string width - final int fontHeight = fm.getHeight(); - final GraphPositionPanel graphPositionPanel = OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPositionPanel(); - final int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom(); - final boolean zoomedOut = OpenLogViewer.getInstance().getEntireGraphingPanel().isZoomedOutBeyondOneToOne(); - int snappedDataPosition = xMouseCoord; - if (!zoomedOut && zoom > 1) { - snappedDataPosition = graphPositionPanel.getBestSnappingPosition(xMouseCoord); - } - g2d.setColor(vertBar); - g2d.drawLine(d.width / 2, 0, d.width / 2, d.height); // center position line - g2d.drawLine(snappedDataPosition, 0, snappedDataPosition, d.height); // mouse cursor line - - final MultiGraphLayeredPane multigGraph = OpenLogViewer.getInstance().getMultiGraphLayeredPane(); - for (int i = 0; i < multigGraph.getComponentCount(); i++) { - if (multigGraph.getComponent(i) instanceof SingleGraphPanel) { - final SingleGraphPanel singleGraph = (SingleGraphPanel) multigGraph.getComponent(i); - g2d.setColor(textBackground); - String mouseData = singleGraph.getMouseInfo(snappedDataPosition, dataWidth); - mouseData = mouseData + " " + singleGraph.getData().getName(); - final int stringWidth = fm.stringWidth(mouseData); - g2d.fillRect(snappedDataPosition - 2 + INFO_DISPLAY_OFFSET, - yMouseCoord + 2 + (fontHeight * i), - stringWidth + 4, - fontHeight); - g2d.setColor(singleGraph.getColor()); - g2d.drawString(mouseData, - snappedDataPosition + INFO_DISPLAY_OFFSET, - yMouseCoord + fontHeight + (fontHeight * i)); - } - } - } - } - } - } - - public final void setLog(final GenericLog log) { - genLog = log; - this.repaint(); - } - - private int getWidestDataWidth() { - String widestDataToDisplay = ""; - final MultiGraphLayeredPane multigGraph = OpenLogViewer.getInstance().getMultiGraphLayeredPane(); - for (int i = 0; i < multigGraph.getComponentCount(); i++) { - if (multigGraph.getComponent(i) instanceof SingleGraphPanel) { - final SingleGraphPanel singleGraph = (SingleGraphPanel) multigGraph.getComponent(i); - final String minValue = MathUtils.roundDecimalPlaces(singleGraph.getData().getMinValue(), SingleGraphPanel.DECIMAL_PLACES); - final String maxValue = MathUtils.roundDecimalPlaces(singleGraph.getData().getMaxValue(), SingleGraphPanel.DECIMAL_PLACES); - if (minValue.length() > widestDataToDisplay.length()) { - widestDataToDisplay = minValue; - } - if (maxValue.length() > widestDataToDisplay.length()) { - widestDataToDisplay = maxValue; - } - } - } - return widestDataToDisplay.length(); - } - - @Override - public final void mouseEntered(final MouseEvent e) { - shouldDraw = true; - } - - @Override - public final void mouseExited(final MouseEvent e) { - if (!e.isShiftDown()) { - // Old default behaviour - shouldDraw = false; - repaint(); - } // else leave coordinates alone - } - - @Override - public final void mouseMoved(final MouseEvent e) { - if (!e.isShiftDown()) { - xMouseCoord = e.getX(); - yMouseCoord = e.getY(); - repaint(); - } // else hold position - } - - @Override - public void mouseClicked(final MouseEvent e) { - } - - @Override - public void mousePressed(final MouseEvent e) { - } - - @Override - public void mouseReleased(final MouseEvent e) { - } - - @Override - public void mouseDragged(final MouseEvent e) { - - } + private static final long serialVersionUID = 1L; + + private static final int LEFT_MARGIN_OFFSET = 10; + private static final int ONE_TEXTUAL_HEIGHT = 20; + private static final int FONT_SIZE = 12; + private static final int INFO_DISPLAY_OFFSET = 4; + private static final Font HOVER_FONT = new Font(Font.MONOSPACED, Font.PLAIN, FONT_SIZE); + + private final ResourceBundle labels; + private final Color vertBar = new Color(255, 255, 255, 100); + private final Color textBackground = new Color(0, 0, 0, 170); + + private GenericLog genLog; + private int xMouseCoord; + private int yMouseCoord; + private boolean shouldDraw; + + public InfoPanel(final ResourceBundle labels) { + this.labels = labels; + setOpaque(false); + } + + @Override + public final void paintComponent(final Graphics g) { + super.paintComponent(g); + + if (!this.getSize().equals(this.getParent().getSize())) { + this.setSize(this.getParent().getSize()); + } + + g.setFont(HOVER_FONT); // Required to keep font consistent when using Mac L&F + if (genLog == null) { + g.setColor(Color.RED); + g.drawString(labels.getString(Text.NO_LOG_LOADED), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT); + } else { + if (genLog.getLogStatus() == GenericLog.LogState.LOG_LOADING) { + g.setColor(Color.red); + g.drawString(labels.getString(Text.LOADING_LOG), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT); + } else if (genLog.getLogStatus() == GenericLog.LogState.LOG_LOADED) { + if (genLog.getLogStatusMessage() != null) { + g.setColor(Color.RED); + g.drawString(labels.getString(Text.DECODER_CRASHED_PART1), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT); + g.drawString(genLog.getLogStatusMessage(), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT * 2); + g.drawString(labels.getString(Text.DECODER_CRASHED_PART2), LEFT_MARGIN_OFFSET, ONE_TEXTUAL_HEIGHT * 3); + } + if (shouldDraw) { + final int dataWidth = getWidestDataWidth(); + final Dimension d = this.getSize(); + final Graphics2D g2d = (Graphics2D) g; + final FontMetrics fm = g.getFontMetrics(g.getFont()); // For getting string width + final int fontHeight = fm.getHeight(); + final GraphPositionPanel graphPositionPanel = OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPositionPanel(); + final int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom(); + final boolean zoomedOut = OpenLogViewer.getInstance().getEntireGraphingPanel().isZoomedOutBeyondOneToOne(); + int snappedDataPosition = xMouseCoord; + if (!zoomedOut && zoom > 1) { + snappedDataPosition = graphPositionPanel.getBestSnappingPosition(xMouseCoord); + } + g2d.setColor(vertBar); + g2d.drawLine(d.width / 2, 0, d.width / 2, d.height); // center position line + g2d.drawLine(snappedDataPosition, 0, snappedDataPosition, d.height); // mouse cursor line + + final MultiGraphLayeredPane multigGraph = OpenLogViewer.getInstance().getMultiGraphLayeredPane(); + for (int i = 0; i < multigGraph.getComponentCount(); i++) { + if (multigGraph.getComponent(i) instanceof SingleGraphPanel) { + final SingleGraphPanel singleGraph = (SingleGraphPanel) multigGraph.getComponent(i); + g2d.setColor(textBackground); + + String mouseData = singleGraph.getMouseInfo(snappedDataPosition, dataWidth) + " " + singleGraph.getData().getName(); + + final int stringWidth = fm.stringWidth(mouseData); + g2d.fillRect(snappedDataPosition - 2 + INFO_DISPLAY_OFFSET, + yMouseCoord + 2 + (fontHeight * i), + stringWidth + 4, + fontHeight); + g2d.setColor(singleGraph.getColor()); + g2d.drawString(mouseData, + snappedDataPosition + INFO_DISPLAY_OFFSET, + yMouseCoord + fontHeight + (fontHeight * i)); + } + } + } + } + } + } + + public final void setLog(final GenericLog log) { + genLog = log; + this.repaint(); + } + + private int getWidestDataWidth() { + String widestDataToDisplay = ""; + final MultiGraphLayeredPane multigGraph = OpenLogViewer.getInstance().getMultiGraphLayeredPane(); + for (int i = 0; i < multigGraph.getComponentCount(); i++) { + if (multigGraph.getComponent(i) instanceof SingleGraphPanel) { + final SingleGraphPanel singleGraph = (SingleGraphPanel) multigGraph.getComponent(i); + final String minValue = MathUtils.roundDecimalPlaces(singleGraph.getData().getMinValue(), SingleGraphPanel.DECIMAL_PLACES); + final String maxValue = MathUtils.roundDecimalPlaces(singleGraph.getData().getMaxValue(), SingleGraphPanel.DECIMAL_PLACES); + if (minValue.length() > widestDataToDisplay.length()) { + widestDataToDisplay = minValue; + } + if (maxValue.length() > widestDataToDisplay.length()) { + widestDataToDisplay = maxValue; + } + } + } + return widestDataToDisplay.length(); + } + + @Override + public final void mouseEntered(final MouseEvent e) { + shouldDraw = true; + } + + @Override + public final void mouseExited(final MouseEvent e) { + if (!e.isShiftDown()) { + // Old default behaviour + shouldDraw = false; + repaint(); + } // else leave coordinates alone + } + + @Override + public final void mouseMoved(final MouseEvent e) { + if (!e.isShiftDown()) { + xMouseCoord = e.getX(); + yMouseCoord = e.getY(); + repaint(); + } // else hold position + } + + @Override + public void mouseClicked(final MouseEvent e) { + // NO-OP + } + + @Override + public void mousePressed(final MouseEvent e) { + // NO-OP + } + + @Override + public void mouseReleased(final MouseEvent e) { + // NO-OP + } + + @Override + public void mouseDragged(final MouseEvent e) { + // NO-OP + } } diff --git a/src/main/java/org/diyefi/openlogviewer/propertypanel/PropertiesPane.java b/src/main/java/org/diyefi/openlogviewer/propertypanel/PropertiesPane.java index ba9cc37..0e79b99 100644 --- a/src/main/java/org/diyefi/openlogviewer/propertypanel/PropertiesPane.java +++ b/src/main/java/org/diyefi/openlogviewer/propertypanel/PropertiesPane.java @@ -208,25 +208,24 @@ public void actionPerformed(final ActionEvent e) { private void loadProperties() { try { - final Scanner scan = new Scanner(new FileReader(OLVProperties)); - - while (scan.hasNext()) { - final String[] propLine = scan.nextLine().split("="); - final SingleProperty sp = new SingleProperty(); - final String[] prop = propLine[1].split(","); - sp.setHeader(propLine[0]); - sp.setColor(new Color( - Integer.parseInt(prop[0]), - Integer.parseInt(prop[1]), - Integer.parseInt(prop[2]))); - sp.setMin(Double.parseDouble(prop[3])); - sp.setMax(Double.parseDouble(prop[4])); - sp.setTrackIndex(Integer.parseInt(prop[5])); - sp.setActive(Boolean.parseBoolean(prop[6])); - addProperty(sp); + try (Scanner scan = new Scanner(new FileReader(OLVProperties))) { + + while (scan.hasNext()) { + final String[] propLine = scan.nextLine().split("="); + final SingleProperty sp = new SingleProperty(); + final String[] prop = propLine[1].split(","); + sp.setHeader(propLine[0]); + sp.setColor(new Color( + Integer.parseInt(prop[0]), + Integer.parseInt(prop[1]), + Integer.parseInt(prop[2]))); + sp.setMin(Double.parseDouble(prop[3])); + sp.setMax(Double.parseDouble(prop[4])); + sp.setTrackIndex(Integer.parseInt(prop[5])); + sp.setActive(Boolean.parseBoolean(prop[6])); + addProperty(sp); + } } - - scan.close(); } catch (FileNotFoundException fnf) { System.out.print(fnf.toString()); throw new RuntimeException(fnf); @@ -237,8 +236,10 @@ public final void save() { try { removeProperties.clear(); updateProperties(); - final FileWriter fstream = new FileWriter(OLVProperties); - final BufferedWriter out = new BufferedWriter(fstream); + final BufferedWriter out; + try (FileWriter fstream = new FileWriter(OLVProperties)) { + out = new BufferedWriter(fstream); + } for (int i = 0; i < properties.size(); i++) { out.write(properties.get(i).toString()); diff --git a/src/main/java/org/diyefi/openlogviewer/subframes/AboutFrame.java b/src/main/java/org/diyefi/openlogviewer/subframes/AboutFrame.java index 69be485..4348445 100644 --- a/src/main/java/org/diyefi/openlogviewer/subframes/AboutFrame.java +++ b/src/main/java/org/diyefi/openlogviewer/subframes/AboutFrame.java @@ -178,7 +178,7 @@ private JPanel createSouthPanel() { final JPanel southPanel = new JPanel(); southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS)); - addTextToPanel(southPanel, "Built by " + buildInfo.getProperty("git.build.user.name") + " using Maven " + buildInfo.getProperty("maven.version") + LINK_CLOSE); + addTextToPanel(southPanel, "Built by " + buildInfo.getProperty("git.build.user.name") + " using Gradle " + buildInfo.getProperty("gradle.version") + LINK_CLOSE); addTextToPanel(southPanel, "Built on " + buildInfo.getProperty("os.name") + " " + buildInfo.getProperty("os.arch") + " " + buildInfo.getProperty("os.version")); addTextToPanel(southPanel, "Built using Java " + buildInfo.getProperty("java.version") + " on a " + buildInfo.getProperty("java.vm.version") + " VM"); addTextToPanel(southPanel, "Build date and time: " + buildInfo.getProperty("git.build.time")); diff --git a/src/main/java/org/diyefi/openlogviewer/utils/MathUtils.java b/src/main/java/org/diyefi/openlogviewer/utils/MathUtils.java index 78a577b..b15441c 100644 --- a/src/main/java/org/diyefi/openlogviewer/utils/MathUtils.java +++ b/src/main/java/org/diyefi/openlogviewer/utils/MathUtils.java @@ -25,51 +25,54 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * MathUtils is used to provide math functions specific to the project. + * * @author Ben Fenner */ public final class MathUtils { - private static final char DS = DecimalFormatSymbols.getInstance().getDecimalSeparator(); - private static final DecimalFormat CUSTOM = (DecimalFormat) NumberFormat.getNumberInstance(); - private static final DecimalFormat NORMAL = (DecimalFormat) NumberFormat.getNumberInstance(); - static { - CUSTOM.setGroupingUsed(false); - NORMAL.setGroupingUsed(false); - } + private static final char DS = DecimalFormatSymbols.getInstance().getDecimalSeparator(); + private static final DecimalFormat CUSTOM = (DecimalFormat) NumberFormat.getNumberInstance(); + private static final DecimalFormat NORMAL = (DecimalFormat) NumberFormat.getNumberInstance(); + + static { + CUSTOM.setGroupingUsed(false); + NORMAL.setGroupingUsed(false); + } - private MathUtils() { - } + private MathUtils() { + } - /** - * - * @param input - The double you'd like to round the decimal places for - * @param decimalPlaces - The number of decimal places you'd like - * @return the formatted number - */ - public static String roundDecimalPlaces(final double input, final int decimalPlaces) { - // Deal with zero or negative decimal places requested - if (decimalPlaces <= 0) { - return NORMAL.format(Math.round(input)); - } + /** + * @param input - The double you'd like to round the decimal places for + * @param decimalPlaces - The number of decimal places you'd like + * @return the formatted number + */ + public static String roundDecimalPlaces(final double input, final int decimalPlaces) { + // Deal with zero or negative decimal places requested + if (decimalPlaces <= 0) { + return NORMAL.format(Math.round(input)); + } - final StringBuilder format = new StringBuilder("###0" + DS); - final StringBuilder negativeZero = new StringBuilder("-0" + DS); + final String format; + final StringBuilder negativeZero = new StringBuilder("-0" + DS); - for (int i = 0; i < decimalPlaces; i++) { - format.append('0'); - negativeZero.append('0'); - } + format = IntStream + .range(0, decimalPlaces) + .mapToObj(i -> "0" + '0') + .collect(Collectors.joining("", "###0" + DS, "")); - CUSTOM.applyLocalizedPattern(format.toString()); - final StringBuilder output = new StringBuilder(CUSTOM.format(input)); + CUSTOM.applyLocalizedPattern(format); + final StringBuilder output = new StringBuilder(CUSTOM.format(input)); - // Deal with negative zero - if (output.toString().equals(negativeZero.toString())) { - output.deleteCharAt(0); - } + // Deal with negative zero + if (output.toString().equals(negativeZero.toString())) { + output.deleteCharAt(0); + } - return output.toString(); - } + return output.toString(); + } } diff --git a/src/main/resources/build/buildInfo.xml b/src/main/resources/build/buildInfo.xml deleted file mode 100644 index f0852de..0000000 --- a/src/main/resources/build/buildInfo.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - -Maven and Git properties filtered during build and available for use at runtime! - - - - -${project.version} -${project.description} -${project.url} - -${maven.version} -${maven.build.timestamp} - -${project.forum.url} -${project.issueManagement.url} - -${os.name} -${os.arch} -${os.version} - -${java.version} -${java.vm.version} -${java.class.version} - - - -${git.commit.user.name} -${git.commit.user.email} -${git.commit.time} - -${git.build.user.name} -${git.build.user.email} -${git.build.time} - -${git.commit.id.describe} -${git.commit.id.abbrev} -${git.commit.id} - - diff --git a/src/main/resources/buildInfo.properties b/src/main/resources/buildInfo.properties new file mode 100644 index 0000000..b344321 --- /dev/null +++ b/src/main/resources/buildInfo.properties @@ -0,0 +1,4 @@ +project.version=${version} +project.description=${description} + +gradle.version=${gradle.gradleVersion} \ No newline at end of file diff --git a/src/main/resources/log4j2.properties b/src/main/resources/log4j2.properties new file mode 100644 index 0000000..c641461 --- /dev/null +++ b/src/main/resources/log4j2.properties @@ -0,0 +1,14 @@ +#---- Categories ---- +log4j.rootLogger = INFO, STDOUT, LOGFILE + +#---- Appenders ---- +log4j.appender.STDOUT = org.apache.log4j.ConsoleAppender +log4j.appender.STDOUT.Target = System.out +log4j.appender.STDOUT.layout = org.apache.log4j.PatternLayout +log4j.appender.STDOUT.layout.ConversionPattern=OpenLogViewer %d [%t] %-5p %c - %m%n + +log4j.appender.LOGFILE = org.apache.log4j.FileAppender +log4j.appender.LOGFILE.File = test.log +log4j.appender.LOGFILE.Append = false +log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout +log4j.appender.LOGFILE.layout.ConversionPattern=OpenLogViewer %d [%t] %-5p %c - %m%n \ No newline at end of file diff --git a/src/site/fredsChecks.xml b/src/site/fredsChecks.xml deleted file mode 100644 index 41fed64..0000000 --- a/src/site/fredsChecks.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/site/pmd/rulesets/controversial.xml b/src/site/pmd/rulesets/controversial.xml deleted file mode 100644 index 669efef..0000000 --- a/src/site/pmd/rulesets/controversial.xml +++ /dev/null @@ -1,622 +0,0 @@ - - - - - -The Controversial ruleset contains rules that, for whatever reason, are considered controversial. -They are held here to allow people to include them as they see fit within their custom rulesets. - - - - -This rule detects when a constructor is not necessary; i.e., when there is only one constructor, -its public, has an empty body, and takes no arguments. - - 3 - - - - - - - - - - - - - - -Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type -of assignment is an indication that the programmer doesn't completely understand what is going on in the code. - -NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection. - - 3 - - - - - - - -Avoid assignments in operands; this can make code more complicated and harder to read. - - 3 - - - - - - - -Each class should declare at least one constructor. - - 3 - - - - - - - - - - - - - - -Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change. - - 4 - - - - - - - -A suspicious octal escape sequence was found inside a String literal. -The Java language specification (section 3.10.6) says an octal -escape sequence inside a literal String shall consist of a backslash -followed by: - - OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit - -Any octal escape sequence followed by non-octal digits can be confusing, -e.g. "\038" is interpreted as the octal escape sequence "\03" followed by -the literal character "8". - - 3 - - - - - - - -Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. - - 3 - - - - - - - - - - - - - - -Use bitwise inversion to invert boolean values - it's the fastest way to do this. -See http://www.javaspecialists.co.za/archive/newsletter.do?issue=042&locale=en_US for specific details - - 3 - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - - - 4 - - - - 1] - ]]> - - - - - - - - - - - - - 4 - - - - - - - - - - - - - -When you write a public method, you should be thinking in terms of an API. If your method is public, it means other class -will use it, therefore, you want (or need) to offer a comprehensive and evolutive API. If you pass a lot of information -as a simple series of Strings, you may think of using an Object to represent all those information. You'll get a simplier -API (such as doWork(Workload workload), rather than a tedious series of Strings) and more importantly, if you need at some -point to pass extra data, you'll be able to do so by simply modifying or extending Workload without any modification to -your API. - - 3 - - - - 3 -] -]]> - - - - - - - - - diff --git a/src/site/pmd/rulesets/coupling.xml b/src/site/pmd/rulesets/coupling.xml deleted file mode 100644 index b3322a5..0000000 --- a/src/site/pmd/rulesets/coupling.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - - - -Rules which find instances of high or inappropriate coupling between objects and packages. - - - - -This rule counts the number of unique attributes, local variables, and return types within an object. -A number higher than the specified threshold can indicate a high degree of coupling. - - 3 - - - - - - - -A high number of imports can indicate a high degree of coupling within an object. This rule -counts the number of unique imports and reports a violation if the count is above the -user-specified threshold. - - 3 - - - - - - - -The use of implementation types as object references limits your ability to use alternate -implementations in the future as requirements change. Whenever available, referencing objects -by their interface types provides much more flexibility. - - 3 - - - - - - - - -The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce coupling between classes or objects. -See also the references: -Andrew Hunt, David Thomas, and Ward Cunningham. The Pragmatic Programmer. From Journeyman to Master. Addison-Wesley Longman, Amsterdam, October 1999.; -K.J. Lieberherr and I.M. Holland. Assuring good style for object-oriented programs. Software, IEEE, 6(5):38–48, 1989.; -http://www.ccs.neu.edu/home/lieber/LoD.html; -http://en.wikipedia.org/wiki/Law_of_Demeter - - 3 - - - - - - - \ No newline at end of file diff --git a/src/site/pmd/rulesets/design.xml b/src/site/pmd/rulesets/design.xml deleted file mode 100644 index d89cff8..0000000 --- a/src/site/pmd/rulesets/design.xml +++ /dev/null @@ -1,1745 +0,0 @@ - - - - - -The Design ruleset contains rules that flag suboptimal code implementations. Alternate approaches -are suggested. - - - - - - - 3 - - - - - - - - -Avoid unnecessary if-then-else statements when returning a boolean. The result of -the conditional test can be returned instead. - - 3 - - - - - - - -Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. - - 3 - - - - - - - - - - - - - - -All switch statements should include a default option to catch any unspecified values. - - 3 - - - - - - - - - - - - - - -Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. - - 3 - -y) { - if (y>z) { - if (z==x) { - // !! too deep - } - } - } - } -} -]]> - - - - - - -Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. - - 2 - - - - - - - -A high ratio of statements to labels in a switch statement implies that the switch statement -is overloaded. Consider moving the statements into new methods or creating subclasses based -on the switch variable. - - 3 - - - - - - - -Calling overridable methods during construction poses a risk of invoking methods on an incompletely -constructed object and can be difficult to debug. -It may leave the sub-class unable to construct its superclass or forced to replicate the construction -process completely within itself, losing the ability to call super(). If the default constructor -contains a call to an overridable method, the subclass may be completely uninstantiable. Note that -this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a -private method bar() that calls a public method buz(), this denotes a problem. - - 1 - - - - - - - -Instantiation by way of private constructors from outside of the constructor's class often causes the -generation of an accessor. A factory method, or non-privatization of the constructor can eliminate this -situation. The generated class file is actually an interface. It gives the accessing class the ability -to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter. -This turns a private constructor effectively into one with package scope, and is challenging to discern. - - 3 - - - - - - - -If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead -in each object at runtime. - - 3 - - - - - - - - - - - - - - - -Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after use. - - 3 - - - - - - - -A non-static initializer block will be called any time a constructor is invoked (just prior to -invoking the constructor). While this is a valid language construct, it is rarely used and is -confusing. - - 3 - - - - - - - - - - - - - - -By convention, the default label should be the last label in a switch statement. - - 3 - - - - - - - - - - - - - - -A non-case label (e.g. a named break/continue label) was present in a switch statement. -This legal, but confusing. It is easy to mix up the case labels and the non-case labels. - - 3 - - - - - - - - - - - - - - -Calls to a collection's toArray() method should specify target arrays sized to match the size of the -collection. Initial arrays that are too small are discarded in favour of new ones that have to be created -that are the proper size. - - 3 - - - - - - - - - - - - - - - -Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation -precision when comparing floating point numbers these are likely to cause logic errors. - - 3 - - - - - - - - - - - - - - -Tests for null should not use the equals() method. The '==' operator should be used instead. - - 1 - - - - - - - - - - - - - - -Avoid instantiating an object just to call getClass() on it; use the .class public member instead. - - 4 - - - - - - - - - - - - - - -Avoid idempotent operations - they have no effect. - - 3 - - - - - - - - -Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate -formatting is used. - - 3 - - - - - - - - - - - - - - -Identifies private fields whose values never change once they are initialized either in the declaration -of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. - - 3 - - - - - - - - -When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that -have unusual conventions, i.e. Turkish. - - 3 - - - - - - - - - - - - - - -Do not use protected fields in final classes since they cannot be subclassed. -Clarify your intent by using private or package access modifiers instead. - - 3 - - - - - - - - - - - - - - -Identifies a possible unsafe usage of a static field. - - 3 - - - - - - - -A class that has private constructors and does not have any static methods or fields cannot be used. - - 3 - - - - 0 - and count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) = count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private='true']) ) -and -count(.//MethodDeclaration[@Static='true'])=0 -and -count(.//FieldDeclaration[@Private='false'][@Static='true'])=0 -] - ]]> - - - - - - - - - - - -Method-level synchronization can cause problems when new code is added to the method. -Block-level synchronization helps to ensure that only the code that needs synchronization -gets it. - - 3 - - - - - - - - - - - - - - -Switch statements without break or return statements for each case option -may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through. - - 3 - - - - - - - - - - - - - - - -Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only -one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead. - - 3 - - - - - - - - - - - - - - -Each caught exception type should be handled in its own catch clause. - - 3 - - - - - - - - - - - - - - -The abstract class does not contain any abstract methods. An abstract class suggests -an incomplete implementation, which is to be completed by subclasses implementing the -abstract methods. If the class is intended to be used as a base class only (not to be instantiated -directly) a protected constructor can be provided prevent direct instantiation. - - 3 - - - - - - - - - - - - - -No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. - - 3 - - - - - - - - - - - - - - -Use equals() to compare object references; avoid comparing them with ==. - - 3 - - - - - - - - -Position literals first in comparisons, if the second argument is null then NullPointerExceptions -can be avoided, they will just return false. - - 3 - - - - - - - - - - - - - - -Avoid the creation of unnecessary local variables - - 3 - - - - - - - -Non-thread safe singletons can result in bad state changes. Eliminate -static singletons if possible by instantiating the object directly. Static -singletons are usually not needed as only a single instance exists anyway. -Other possible fixes are to synchronize the entire method or to use an -initialize-on-demand holder class (do not use the double-check idiom). - -See Effective Java, item 48. - - 3 - - - - - - - -Uncommented Empty Method finds instances where a method does not contain -statements, but there is no comment. By explicitly commenting empty methods -it is easier to distinguish between intentional (commented) and unintentional -empty methods. - - 3 - - - - - - - - - - - - - - -Uncommented Empty Constructor finds instances where a constructor does not -contain statements, but there is no comment. By explicitly commenting empty -constructors it is easier to distinguish between intentional (commented) -and unintentional empty constructors. - - 3 - - - - - - - - - - - - - - - -An interface should be used only to characterize the external behaviour of an -implementing class: using an interface as a container of constants is a poor -usage pattern and not recommended. - - 3 - - - - 0 - ] - ]]> - - - - - - - - - - -SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances -for each thread. If multiple threads must access a static formatter, the formatter must be -synchronized either on method or block level. - - 3 - - - - - - - -Throwing a new exception from a catch block without passing the original exception into the -new exception will cause the original stack trace to be lost making it difficult to debug -effectively. - - 3 - - - - - - - -The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements. -Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method. - - 3 - - - - - - - -A class with only private constructors should be final, unless the private constructor -is invoked by a inner class. - - 1 - - - = 1 ] -[count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[(@Public = 'true') or (@Protected = 'true') or (@PackagePrivate = 'true')]) = 0 ] -[not(.//ClassOrInterfaceDeclaration)] - ]]> - - - - - - - - -Empty methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate -usage by developers who should be implementing their own versions in the concrete subclasses. - - 1 - - - - - - - - - - - - - - - - - 3 - - - - - -For any method that returns an array, it is a better to return an empty array rather than a -null reference. This removes the need for null checking all results and avoids inadvertent -NullPointerExceptions. - - 1 - - - - - - - - - - - - -If an abstract class does not provides any methods, it may be acting as a simple data container -that is not meant to be instantiated. In this case, it is probably better to use a private or -protected constructor in order to prevent instantiation than make the class misleadingly abstract. - - 1 - - - - - - - - - - - - - - -Switch statements are indended to be used to support complex branching behaviour. Using a switch for only a few -cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the -if-then statement to increase code readability. - - 1 - - - - - - - - - - - - - - - - -Use opposite operator instead of negating the whole expression with a logic complement operator. - - 3 - - - - - - - - - = - return false; - - return true; -} - ]]> - - - - - -Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic -sugar provides flexibility for users of these methods and constructors, allowing them to avoid -having to deal with the creation of an array. - - 4 - - - - - - - - - - -Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. - - 3 - - - - 0] - ]]> - - - - - - - - - - -The God Class rule detects the God Class design flaw using metrics. God classes do too many things, -are very big and overly complex. They should be split apart to be more object-oriented. -The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". -The violations are reported against the entire class. See also the references: -Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: -Using Software Metrics to Characterize, Evaluate, and Improve the Design -of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. - - 3 - - diff --git a/src/test/java/org/diyefi/openlogviewer/FileExtensionsTest.java b/src/test/java/org/diyefi/openlogviewer/FileExtensionsTest.java new file mode 100644 index 0000000..13db93d --- /dev/null +++ b/src/test/java/org/diyefi/openlogviewer/FileExtensionsTest.java @@ -0,0 +1,48 @@ +package org.diyefi.openlogviewer; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +class FileExtensionsTest { + + private static Stream fileExtensionProvider() { + return Stream.of( + Arguments.of(FileExtensions.STAR_DOT, "*."), + Arguments.of(FileExtensions.LA, "la"), + Arguments.of(FileExtensions.BIN, "bin"), + Arguments.of(FileExtensions.BIN, "bin"), + Arguments.of(FileExtensions.CSV, "csv"), + Arguments.of(FileExtensions.LOG, "log"), + Arguments.of(FileExtensions.XLS, "xls"), + Arguments.of(FileExtensions.MSL, "msl")); + } + + @ParameterizedTest(name = "run #{index} with [{arguments}]") + @MethodSource("fileExtensionProvider") + void shouldReturnCorrectExtensionStringForGivenEnum(FileExtensions given, String expected) { + // ARRANGE + + // ACT + String result = given.getExtension(); + + // ASSERT + assertThat(result).isEqualTo(expected); + } + + @ParameterizedTest(name = "run #{index} with [{arguments}]") + @MethodSource("fileExtensionProvider") + void shouldReturnCorrectEnumforGivenExtensionString(FileExtensions expected, String given) { + // ARRANGE + + // ACT + FileExtensions result = FileExtensions.getByExtension(given); + + // ASSERT + assertThat(result).isEqualTo(expected); + } +} \ No newline at end of file diff --git a/src/test/java/org/diyefi/openlogviewer/LanguageTextTest.java b/src/test/java/org/diyefi/openlogviewer/LanguageTextTest.java deleted file mode 100644 index 6a7f5d8..0000000 --- a/src/test/java/org/diyefi/openlogviewer/LanguageTextTest.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.diyefi.openlogviewer; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Locale; -import java.util.ResourceBundle; -import java.util.Set; - -import org.junit.Ignore; -import org.junit.Test; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.Validate; -import org.diyefi.openlogviewer.Text; - -import static org.junit.Assert.*; - - -/** - * A set of tests to shake down the translations setup. It won't catch defaults pasted into the non-English file, but that shouldn't be done anyway. - * - * @author Fred Cooke - */ -public class LanguageTextTest { - - private static final Field[] keys; - static { - keys = Text.class.getDeclaredFields(); - } - - - private final Set keySet = new HashSet(); - - /** - * Ensure that no keys are themselves blank, forgotten or duplicated. - * - * Doing it here gets us a line number and blatant stack traces dumped. - */ - public LanguageTextTest() { - Validate.isTrue(keys.length > 0); - // System.out.println("Text lookups: " + keys.length); - for (Field k : keys) { - if (!Modifier.isTransient(k.getModifiers())) { - String key = null; - try { - key = (String)k.get(null); - } catch (IllegalAccessException e) { - e.printStackTrace(); - Validate.isTrue(false); // Should never happen - } - Validate.notBlank(key); // No empties/blanks/nulls - Validate.isTrue(keySet.add(key)); // No dupes - } // Ignore cobertura's implanted field :-p - } - } - - // Individual tests below so as to see what went wrong, at a glance - - @Test - public void testEnglishComplete() { - testLanguageComplete(Locale.ENGLISH, ""); - } - - @Test - public void testEnglishNoUnused() { - testNoUnusedText(Locale.ENGLISH, ""); - } - - @Test - @Ignore("Not yet complete!") - public void testSpanishComplete() { - testLanguageComplete(new Locale("es"), "_es"); - } - - @Test - public void testSpanishNoUnused() { - testNoUnusedText(new Locale("es"), "_es"); - } - - /** - * Ensure that all keys for this language have a valid label - * - * @param locale - * @param suffix - */ - private void testLanguageComplete(Locale locale, String suffix) { - ResourceBundle labels = getLabels(locale, suffix); - - for (String key : keySet) { - String value = labels.getString(key); - // System.out.println("Key/value: " + key + " = \"" + value + "\""); // Useful while debugging - assertTrue(StringUtils.isNotBlank(value)); - } - } - - /** - * Ensure that everything in the properties files is referred to by a field in the text class. - * - * @param locale - * @param suffix - */ - private void testNoUnusedText(Locale locale, String suffix) { - ResourceBundle labels = getLabels(locale, suffix); - - for (String label : labels.keySet()) { - // System.out.println("Label: " + label); // Useful while debugging - assertTrue(keySet.contains(label)); - } - } - - private ResourceBundle getLabels(Locale locale, String suffix) { - return ResourceBundle.getBundle(OpenLogViewer.class.getPackage().getName() + ".Labels" + suffix , locale); - } -} diff --git a/src/test/java/org/diyefi/openlogviewer/decoder/FreeEMSBinaryTest.java b/src/test/java/org/diyefi/openlogviewer/decoder/FreeEMSBinaryTest.java deleted file mode 100644 index 7009b4c..0000000 --- a/src/test/java/org/diyefi/openlogviewer/decoder/FreeEMSBinaryTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - */ -package org.diyefi.openlogviewer.decoder; - -import junit.framework.TestCase; - -public class FreeEMSBinaryTest extends TestCase { - - public void testChecksum(){ - assertEquals(true, true); - } - - public void testFail(){ - assertTrue(true); - } - - public void testPass(){ - assertTrue(true); - } -} diff --git a/src/test/java/org/diyefi/openlogviewer/utils/MathUtilsTest.java b/src/test/java/org/diyefi/openlogviewer/utils/MathUtilsTest.java deleted file mode 100644 index bf3c30c..0000000 --- a/src/test/java/org/diyefi/openlogviewer/utils/MathUtilsTest.java +++ /dev/null @@ -1,197 +0,0 @@ -package org.diyefi.openlogviewer.utils; - -import java.util.Locale; - -import junit.framework.TestCase; - -public class MathUtilsTest extends TestCase { - - public MathUtilsTest(String name) { - super(name); - } - - protected void setUp() throws Exception { - super.setUp(); - Locale.setDefault(Locale.US); // Ensure tests pass in Europe! :-) - } - - public void testRoundDecimalPlaces(){ - int decimalPlaces = -1; - assertEquals("0", MathUtils.roundDecimalPlaces(0D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(1D/3D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.5D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(2D/3D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(1.3333333D, decimalPlaces)); - assertEquals("2", MathUtils.roundDecimalPlaces(1.5D, decimalPlaces)); - assertEquals("2", MathUtils.roundDecimalPlaces(1.6666666D, decimalPlaces)); - assertEquals("22", MathUtils.roundDecimalPlaces(22.3333333D, decimalPlaces)); - assertEquals("23", MathUtils.roundDecimalPlaces(22.6666666D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.99D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.999D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.9999D, decimalPlaces)); - assertEquals("12345678912345678", MathUtils.roundDecimalPlaces(12345678912345678D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(0.0001234D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(0.0006789D, decimalPlaces)); - - assertEquals("0", MathUtils.roundDecimalPlaces(-0D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-1D/3D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-0.5D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-2D/3D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-1.3333333D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-1.5D, decimalPlaces)); - assertEquals("-2", MathUtils.roundDecimalPlaces(-1.6666666D, decimalPlaces)); - assertEquals("-22", MathUtils.roundDecimalPlaces(-22.3333333D, decimalPlaces)); - assertEquals("-23", MathUtils.roundDecimalPlaces(-22.6666666D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-0.99D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-0.999D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-0.9999D, decimalPlaces)); - assertEquals("-12345678912345678", MathUtils.roundDecimalPlaces(-12345678912345678D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-0.0001234D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-0.0006789D, decimalPlaces)); - - decimalPlaces = 0; - assertEquals("0", MathUtils.roundDecimalPlaces(0D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(1D/3D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.5D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(2D/3D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(1.3333333D, decimalPlaces)); - assertEquals("2", MathUtils.roundDecimalPlaces(1.5D, decimalPlaces)); - assertEquals("2", MathUtils.roundDecimalPlaces(1.6666666D, decimalPlaces)); - assertEquals("22", MathUtils.roundDecimalPlaces(22.3333333D, decimalPlaces)); - assertEquals("23", MathUtils.roundDecimalPlaces(22.6666666D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.99D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.999D, decimalPlaces)); - assertEquals("1", MathUtils.roundDecimalPlaces(0.9999D, decimalPlaces)); - assertEquals("12345678912345678", MathUtils.roundDecimalPlaces(12345678912345678D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(0.0001234D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(0.0006789D, decimalPlaces)); - - assertEquals("0", MathUtils.roundDecimalPlaces(-0D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-1D/3D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-0.5D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-2D/3D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-1.3333333D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-1.5D, decimalPlaces)); - assertEquals("-2", MathUtils.roundDecimalPlaces(-1.6666666D, decimalPlaces)); - assertEquals("-22", MathUtils.roundDecimalPlaces(-22.3333333D, decimalPlaces)); - assertEquals("-23", MathUtils.roundDecimalPlaces(-22.6666666D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-0.99D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-0.999D, decimalPlaces)); - assertEquals("-1", MathUtils.roundDecimalPlaces(-0.9999D, decimalPlaces)); - assertEquals("-12345678912345678", MathUtils.roundDecimalPlaces(-12345678912345678D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-0.0001234D, decimalPlaces)); - assertEquals("0", MathUtils.roundDecimalPlaces(-0.0006789D, decimalPlaces)); - - decimalPlaces = 1; - assertEquals("0.0", MathUtils.roundDecimalPlaces(0D, decimalPlaces)); - assertEquals("0.3", MathUtils.roundDecimalPlaces(1D/3D, decimalPlaces)); - assertEquals("0.5", MathUtils.roundDecimalPlaces(0.5D, decimalPlaces)); - assertEquals("0.7", MathUtils.roundDecimalPlaces(2D/3D, decimalPlaces)); - assertEquals("1.3", MathUtils.roundDecimalPlaces(1.3333333D, decimalPlaces)); - assertEquals("1.5", MathUtils.roundDecimalPlaces(1.5D, decimalPlaces)); - assertEquals("1.7", MathUtils.roundDecimalPlaces(1.6666666D, decimalPlaces)); - assertEquals("22.3", MathUtils.roundDecimalPlaces(22.3333333D, decimalPlaces)); - assertEquals("22.7", MathUtils.roundDecimalPlaces(22.6666666D, decimalPlaces)); - assertEquals("1.0", MathUtils.roundDecimalPlaces(0.99D, decimalPlaces)); - assertEquals("1.0", MathUtils.roundDecimalPlaces(0.999D, decimalPlaces)); - assertEquals("1.0", MathUtils.roundDecimalPlaces(0.9999D, decimalPlaces)); - assertEquals("12345678912345678.0", MathUtils.roundDecimalPlaces(12345678912345678D, decimalPlaces)); - assertEquals("0.0", MathUtils.roundDecimalPlaces(0.0001234D, decimalPlaces)); - assertEquals("0.0", MathUtils.roundDecimalPlaces(0.0006789D, decimalPlaces)); - - assertEquals("0.0", MathUtils.roundDecimalPlaces(-0D, decimalPlaces)); - assertEquals("-0.3", MathUtils.roundDecimalPlaces(-1D/3D, decimalPlaces)); - assertEquals("-0.5", MathUtils.roundDecimalPlaces(-0.5D, decimalPlaces)); - assertEquals("-0.7", MathUtils.roundDecimalPlaces(-2D/3D, decimalPlaces)); - assertEquals("-1.3", MathUtils.roundDecimalPlaces(-1.3333333D, decimalPlaces)); - assertEquals("-1.5", MathUtils.roundDecimalPlaces(-1.5D, decimalPlaces)); - assertEquals("-1.7", MathUtils.roundDecimalPlaces(-1.6666666D, decimalPlaces)); - assertEquals("-22.3", MathUtils.roundDecimalPlaces(-22.3333333D, decimalPlaces)); - assertEquals("-22.7", MathUtils.roundDecimalPlaces(-22.6666666D, decimalPlaces)); - assertEquals("-1.0", MathUtils.roundDecimalPlaces(-0.99D, decimalPlaces)); - assertEquals("-1.0", MathUtils.roundDecimalPlaces(-0.999D, decimalPlaces)); - assertEquals("-1.0", MathUtils.roundDecimalPlaces(-0.9999D, decimalPlaces)); - assertEquals("-12345678912345678.0", MathUtils.roundDecimalPlaces(-12345678912345678D, decimalPlaces)); - assertEquals("0.0", MathUtils.roundDecimalPlaces(-0.0001234D, decimalPlaces)); - assertEquals("0.0", MathUtils.roundDecimalPlaces(-0.0006789D, decimalPlaces)); - - - decimalPlaces = 2; - assertEquals("0.00", MathUtils.roundDecimalPlaces(0D, decimalPlaces)); - assertEquals("0.33", MathUtils.roundDecimalPlaces(1D/3D, decimalPlaces)); - assertEquals("0.50", MathUtils.roundDecimalPlaces(0.5D, decimalPlaces)); - assertEquals("0.67", MathUtils.roundDecimalPlaces(2D/3D, decimalPlaces)); - assertEquals("1.33", MathUtils.roundDecimalPlaces(1.3333333D, decimalPlaces)); - assertEquals("1.50", MathUtils.roundDecimalPlaces(1.5D, decimalPlaces)); - assertEquals("1.67", MathUtils.roundDecimalPlaces(1.6666666D, decimalPlaces)); - assertEquals("22.33", MathUtils.roundDecimalPlaces(22.3333333D, decimalPlaces)); - assertEquals("22.67", MathUtils.roundDecimalPlaces(22.6666666D, decimalPlaces)); - assertEquals("0.99", MathUtils.roundDecimalPlaces(0.99D, decimalPlaces)); - assertEquals("1.00", MathUtils.roundDecimalPlaces(0.999D, decimalPlaces)); - assertEquals("1.00", MathUtils.roundDecimalPlaces(0.9999D, decimalPlaces)); - assertEquals("12345678912345678.00", MathUtils.roundDecimalPlaces(12345678912345678D, decimalPlaces)); - assertEquals("0.00", MathUtils.roundDecimalPlaces(0.0001234D, decimalPlaces)); - assertEquals("0.00", MathUtils.roundDecimalPlaces(0.0006789D, decimalPlaces)); - - assertEquals("0.00", MathUtils.roundDecimalPlaces(-0D, decimalPlaces)); - assertEquals("-0.33", MathUtils.roundDecimalPlaces(-1D/3D, decimalPlaces)); - assertEquals("-0.50", MathUtils.roundDecimalPlaces(-0.5D, decimalPlaces)); - assertEquals("-0.67", MathUtils.roundDecimalPlaces(-2D/3D, decimalPlaces)); - assertEquals("-1.33", MathUtils.roundDecimalPlaces(-1.3333333D, decimalPlaces)); - assertEquals("-1.50", MathUtils.roundDecimalPlaces(-1.5D, decimalPlaces)); - assertEquals("-1.67", MathUtils.roundDecimalPlaces(-1.6666666D, decimalPlaces)); - assertEquals("-22.33", MathUtils.roundDecimalPlaces(-22.3333333D, decimalPlaces)); - assertEquals("-22.67", MathUtils.roundDecimalPlaces(-22.6666666D, decimalPlaces)); - assertEquals("-0.99", MathUtils.roundDecimalPlaces(-0.99D, decimalPlaces)); - assertEquals("-1.00", MathUtils.roundDecimalPlaces(-0.999D, decimalPlaces)); - assertEquals("-1.00", MathUtils.roundDecimalPlaces(-0.9999D, decimalPlaces)); - assertEquals("-12345678912345678.00", MathUtils.roundDecimalPlaces(-12345678912345678D, decimalPlaces)); - assertEquals("0.00", MathUtils.roundDecimalPlaces(-0.0001234D, decimalPlaces)); - assertEquals("0.00", MathUtils.roundDecimalPlaces(-0.0006789D, decimalPlaces)); - - - decimalPlaces = 6; - assertEquals("0.000000", MathUtils.roundDecimalPlaces(0D, decimalPlaces)); - assertEquals("0.333333", MathUtils.roundDecimalPlaces(1D/3D, decimalPlaces)); - assertEquals("0.500000", MathUtils.roundDecimalPlaces(0.5D, decimalPlaces)); - assertEquals("0.666667", MathUtils.roundDecimalPlaces(2D/3D, decimalPlaces)); - assertEquals("1.333333", MathUtils.roundDecimalPlaces(1.3333333D, decimalPlaces)); - assertEquals("1.500000", MathUtils.roundDecimalPlaces(1.5D, decimalPlaces)); - assertEquals("1.666667", MathUtils.roundDecimalPlaces(1.6666666D, decimalPlaces)); - assertEquals("22.333333", MathUtils.roundDecimalPlaces(22.3333333D, decimalPlaces)); - assertEquals("22.666667", MathUtils.roundDecimalPlaces(22.6666666D, decimalPlaces)); - assertEquals("0.990000", MathUtils.roundDecimalPlaces(0.99D, decimalPlaces)); - assertEquals("0.999000", MathUtils.roundDecimalPlaces(0.999D, decimalPlaces)); - assertEquals("0.999900", MathUtils.roundDecimalPlaces(0.9999D, decimalPlaces)); - assertEquals("12345678912345678.000000", MathUtils.roundDecimalPlaces(12345678912345678D, decimalPlaces)); - assertEquals("0.000123", MathUtils.roundDecimalPlaces(0.0001234D, decimalPlaces)); - assertEquals("0.000679", MathUtils.roundDecimalPlaces(0.0006789D, decimalPlaces)); - - assertEquals("0.000000", MathUtils.roundDecimalPlaces(-0D, decimalPlaces)); - assertEquals("-0.333333", MathUtils.roundDecimalPlaces(-1D/3D, decimalPlaces)); - assertEquals("-0.500000", MathUtils.roundDecimalPlaces(-0.5D, decimalPlaces)); - assertEquals("-0.666667", MathUtils.roundDecimalPlaces(-2D/3D, decimalPlaces)); - assertEquals("-1.333333", MathUtils.roundDecimalPlaces(-1.3333333D, decimalPlaces)); - assertEquals("-1.500000", MathUtils.roundDecimalPlaces(-1.5D, decimalPlaces)); - assertEquals("-1.666667", MathUtils.roundDecimalPlaces(-1.6666666D, decimalPlaces)); - assertEquals("-22.333333", MathUtils.roundDecimalPlaces(-22.3333333D, decimalPlaces)); - assertEquals("-22.666667", MathUtils.roundDecimalPlaces(-22.6666666D, decimalPlaces)); - assertEquals("-0.990000", MathUtils.roundDecimalPlaces(-0.99D, decimalPlaces)); - assertEquals("-0.999000", MathUtils.roundDecimalPlaces(-0.999D, decimalPlaces)); - assertEquals("-0.999900", MathUtils.roundDecimalPlaces(-0.9999D, decimalPlaces)); - assertEquals("-12345678912345678.000000", MathUtils.roundDecimalPlaces(-12345678912345678D, decimalPlaces)); - assertEquals("-0.000123", MathUtils.roundDecimalPlaces(-0.0001234D, decimalPlaces)); - assertEquals("-0.000679", MathUtils.roundDecimalPlaces(-0.0006789D, decimalPlaces)); - } - - public void testRoundDecimalPlacesSpeed(){ - long thePast = System.currentTimeMillis(); - int iterations = 0; - - for (int i = 0; i < iterations; i++){ - testRoundDecimalPlaces(); - } - long elapsedTime = System.currentTimeMillis() - thePast; - System.out.println("Time to complete " + iterations + " iterations of testRoundDecimalPlaces(): " + elapsedTime + "ms"); - } -} diff --git a/src/test/resources/log4j2.properties b/src/test/resources/log4j2.properties new file mode 100644 index 0000000..c641461 --- /dev/null +++ b/src/test/resources/log4j2.properties @@ -0,0 +1,14 @@ +#---- Categories ---- +log4j.rootLogger = INFO, STDOUT, LOGFILE + +#---- Appenders ---- +log4j.appender.STDOUT = org.apache.log4j.ConsoleAppender +log4j.appender.STDOUT.Target = System.out +log4j.appender.STDOUT.layout = org.apache.log4j.PatternLayout +log4j.appender.STDOUT.layout.ConversionPattern=OpenLogViewer %d [%t] %-5p %c - %m%n + +log4j.appender.LOGFILE = org.apache.log4j.FileAppender +log4j.appender.LOGFILE.File = test.log +log4j.appender.LOGFILE.Append = false +log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout +log4j.appender.LOGFILE.layout.ConversionPattern=OpenLogViewer %d [%t] %-5p %c - %m%n \ No newline at end of file